$ mkdir zhufeng-umi-dva4
$ cd zhufeng-umi-dva4
$ yarn create umi
$ dva new zhufeng-umi-dva
$ cd zhufeng-umi-dva
$ npm start
在浏览器里打开 http://localhost:8000 ,你会看到 dva 的欢迎界面。
cnpm i antd -S
cnpm i babel-plugin-import -D
{
"extraBabelPlugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
]
}
src/router.js
+ <Route path="/" component={IndexPage} />
src/routes/IndexPage.less
src\routes\IndexPage.js
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.less';
import {Layout} from 'antd';
import NavBar from '../components/NavBar';
const {Content} = Layout;
function IndexPage(props) {
return (
<Layout>
<NavBar {...props}/>
<Content>内容</Content>
</Layout>
);
}
export default connect()(IndexPage);
src\components\NavBar\index.js
import {Menu} from 'antd';
import styles from './index.less';
import {Link} from 'dva/router';
import React, { Component } from 'react';
import {Layout} from 'antd';
let logo = require('../../assets/logo.png');
export default class NavBar extends Component {
render() {
return (
<Layout.Header className={styles.header}>
<img src={logo}/>
<Menu className={styles.menu} mode="horizontal" selectedKeys={[this.props.location.pathname]} >
<Menu.Item key="/home"><Link to="/home">主页</Link></Menu.Item>
<Menu.Item key="/user"><Link to="/user">用户管理</Link></Menu.Item>
<Menu.Item key="/profile"><Link to="/profile">个人中心</Link></Menu.Item>
<Menu.Item key="/login"><Link to="/login">登录</Link></Menu.Item>
<Menu.Item key="/register"><Link to="/register">注册</Link></Menu.Item>
</Menu>
</Layout.Header>
)
}
}
src\components\NavBar\index.less
.header{
height:48px;
line-height: 48px;
background-color: #FFF;
img{
height:48px;
}
.menu{
display:inline-block;
height:48px;
}
}
src/routes/IndexPage.js
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.less';
import {Layout} from 'antd';
import NavBar from '../components/NavBar';
import {Route,Switch,Redirect} from 'dva/router';
import Home from './Home';
import User from './User';
import Profile from './Profile';
import Register from './Register';
import Login from './Login';
const {Content} = Layout;
function IndexPage(props) {
return (
<Layout>
<NavBar {...props}/>
<Content>
<Switch>
<Route path="/home" component={Home} />
<Route path="/user" component={User} />
<Route path="/profile" component={Profile} />
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
<Redirect to="/home"/>
</Switch>
</Content>
</Layout>
);
}
export default connect()(IndexPage);
src/router.js
import React from 'react';
import { Router, Switch } from 'dva/router';
import {renderRoutes} from './utils/routes';
import routesConfig from './routeConfig';
function RouterConfig({ history }) {
return (
<Router history={history}>
<Switch>
{renderRoutes(routesConfig)}
</Switch>
</Router>
);
}
export default RouterConfig;
src/routes/IndexPage.js
import React from 'react';
import { connect } from 'dva';
import {Layout} from 'antd';
import NavBar from '../components/NavBar';
import {Switch} from 'dva/router';
import NoMatch from '../components/NoMatch';
import {renderRoutes,renderRedirect} from '../utils/routes';
const {Content} = Layout;
function IndexPage(props) {
return (
<Layout>
<NavBar {...props}/>
<Content>
<Switch>
{renderRoutes(props.routes)}
{renderRedirect('/',true,props.routes)}
<NoMatch/>
</Switch>
</Content>
</Layout>
);
}
export default connect()(IndexPage);
src/utils/routes.js
import {Route,Redirect} from 'dva/router';
export function renderRoutes(routesConfig){
return routesConfig.map(({path,exact=false,component:Component,routes=[]},index)=>(
<Route path={path} exact={exact} key={index} render={props=><Component {...props} routes={routes}/>}/>
))
}
export function renderRedirect(from,exact,routesConfig){
let {path} = routesConfig.find(route=>route.redirect)||routesConfig[0];
return <Redirect exact={exact} from={from} to={path}/>
}
src/routeConfig.js
import IndexPage from './routes/IndexPage';
import Home from './routes/Home';
import User from './routes/User';
import Profile from './routes/Profile';
import Register from './routes/Register';
import Login from './routes/Login';
export default [
{
path:'/',
component:IndexPage,
routes:[
{
path:'/home',
component:Home
},
{
path:'/user',
component:User
},
{
path:'/profile',
component:Profile
},
{
path:'/login',
component:Login
}, {
path:'/register',
component:Register
}
]
}
]
src\components\NoMatch\index.js
import React from 'react'
export default () => {
return (
<div>
此页面不存在
</div>
)
}
src/routeConfig.js
/* import IndexPage from './routes/IndexPage';
import Home from './routes/Home';
import User from './routes/User';
import Profile from './routes/Profile';
import Register from './routes/Register';
import Login from './routes/Login'; */
export default [
{
path:'/',
component:()=>import('./routes/IndexPage'),
routes:[
{
path:'/home',
models:[import('./models/home')],
component:()=>import('./routes/Home')
},
{
path:'/user',
component:()=>import('./routes/User')
},
{
path:'/profile',
component:()=>import('./routes/Profile')
},
{
path:'/login',
component:()=>import('./routes/Login')
}, {
path:'/register',
component:()=>import('./routes/Register')
}
]
}
]
src/router.js
import React from 'react';
import { Router, Switch } from 'dva/router';
import {renderRoutes} from './utils/routes';
import routesConfig from './routeConfig';
function RouterConfig({ history,app }) {
return (
<Router history={history}>
<Switch>
{renderRoutes(routesConfig,app)}
</Switch>
</Router>
);
}
export default RouterConfig;
src/routes/Home/index.js
import React, { Component } from 'react'
import styles from './index.less';
import { connect } from 'dva';
class componentName extends Component {
render() {
return (
<div>
{this.props.title}
</div>
)
}
}
export default connect(state=>state.home)(componentName);
src/routes/IndexPage.js
import React from 'react';
import { connect } from 'dva';
import {Layout} from 'antd';
import NavBar from '../components/NavBar';
import {Switch} from 'dva/router';
import NoMatch from '../components/NoMatch';
import {renderRoutes,renderRedirect} from '../utils/routes';
const {Content} = Layout;
function IndexPage(props) {
return (
<Layout>
<NavBar {...props}/>
<Content>
<Switch>
{renderRoutes(props.routes,props.app)}
{renderRedirect('/',true,props.routes)}
<NoMatch/>
</Switch>
</Content>
</Layout>
);
}
export default connect()(IndexPage);
src/utils/routes.js
import {Route,Redirect} from 'dva/router';
import dynamic from 'dva/dynamic';
export function renderRoutes(routesConfig,app){
return routesConfig.map(({path,exact=false,component,routes=[],models=[]},index)=>(
//<Route path={path} exact={exact} key={index} render={props=><Component {...props} routes={routes}/>}/>
<Route
path={path} exact={exact} key={index}
component={dynamic({
app,
models:()=>models,
component:()=>{
return component().then(result=>{
let Component = result.default || result;
return props=><Component {...props} routes={routes} app={app}/>;
})
}
})}
/>
))
}
export function renderRedirect(from,exact,routesConfig){
let {path} = routesConfig.find(route=>route.redirect)||routesConfig[0];
return <Redirect exact={exact} from={from} to={path}/>
}
src/models/home.js
export default {
namespace: 'home',
state: {
title:'我是首页'
},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
},
},
effects: {
*fetch({ payload }, { call, put }) { // eslint-disable-line
yield put({ type: 'save' });
},
},
reducers: {
save(state, action) {
return { ...state, ...action.payload };
},
},
};
component:()=>{
+ if(authority && !localStorage.getItem('token')){
+ return ()=><Redirect to="/login"/>;
+ }
src/routeConfig.js
{
path:'/profile',
component:()=>import('./routes/Profile'),
+ authority:true
},