1.安装dva-cli
-
npm install dva-cli -g
2.创建应用
dva new dvadashboard
[dvadashboard为项目名]

3.安装mockjs
- npm install mockjs --save
4.配置mockjs
- 打开.roadhogrc.mock.js 设置如下
const fs=require('fs'); const path=require('path'); const mockPath=path.join(__dirname+'/mock'); const mock={}; fs.readdirSync(mockPath).forEach(file=>{ Object.assign(mock,require('./mock/'+file)); }); module.exports=mock;
5.模拟用户管理API
mock文件夹下新建user.js

API设置:
这里只模拟俩个api 1.获取所有用户数据 2.添加用户
const Mock=require('mockjs'); let db=Mock.mock({ 'data|3-6':[{ id:'@id', name:'@name', 'age|18-32':1 }] }); module.exports={ [`GET /api/users`](req,res){ res.status(200).json(db); }, [`POST /api/users`](req,res){ let user=req.body; console.log(req); user.id=Mock.mock('@id'); db.data.push(user); res.status(200).json(user); } }
接下来看一下api能不能使用, 进入项目目录, 执行 npm start 启动
进入默认页面 默认端口号 8000 如下是项目启动后默认页面

访问下api http://localhost:8000/api/users 好了,可以访问 成功返回模拟用户列表数据

6.安装antd
npm install antd babel-plugin-import --save
babel-plugin-import 是用来按需加载 antd 的脚本和样式的
安装完成后,配置使用antd 修改.roadhogrc文件
添加 ["import",{ "libraryName":"antd","style":"css" }] 最后文件如下所示:
{ "entry": "src/index.js", "env": { "development": { "extraBabelPlugins": [ "dva-hmr", "transform-runtime", ["import",{ "libraryName":"antd","style":"css" }] ] }, "production": { "extraBabelPlugins": [ "transform-runtime", ["import",{ "libraryName":"antd","style":"css" }] ] } } }
7.定义路由
- 在src/routes/ 文件夹下新建 usersPage.js
这可能是最简单的一个页面了
import { connect } from 'dva';
const UserPage=()=>{
return (
<div>
<h1>UserPage</h1>
</div>
);
};
export default connect()(UserPage);
- 注册路由信息 修改src/router.js文件
顺手加了个组件动态加载
import React from 'react'; import { Router, Route, Switch } from 'dva/router'; import dynamic from 'dva/dynamic'; import IndexPage from './routes/IndexPage'; function RouterConfig({ history,app }) { const UserPage=dynamic({ app, component:()=>import('./routes/usersPage') }); return ( <Router history={history}> <Switch> <Route path="/" exact component={IndexPage} /> <Route path="/users" exact component={UserPage} /> </Switch> </Router> ); } export default RouterConfig;
查看一下路由配置效果 访问http://localhost:8000/#/users
显示内容了

8.添加与服务端通讯
- 修改src/utils/request.js如下 用于提供基础的ajax数据访问
也有不少使用axio的 具体优缺点还没研究。
import fetch from 'dva/fetch'; const checkStatus=(response)=>{ if(response.status>=200 && response.status<=200){ return response; } const error=new Error(response.statusText); error.response=response; throw error; }; export default async function request(url,options={}) { options.headers={ 'Content-Type':'application/json' } const response=await fetch(url,options); checkStatus(response); const data=await response.json(); return data; }
这里为了理解简单 省略一层 user.service (封装基础ajax通讯 提供业务接口) 在业务层中直接调用request里方法 【只是为了学习方便】
- 然后在src/models下新建user.js
import request from '../utils/request'; const User={ namespace:"user", state:{ list:[], visibleModal:false }, reducers:{ save(state,{ payload:{ data:list } }){ return { ...state, list }; } }, effects:{ * query({},{ call,put }){ const { data }=yield call(request,'/api/users',{ method:'GET' }); yield put({type:'save',payload:{ data }}); }, * create({ payload:{ user } },{ call,put }){ yield call(request,'/api/users',{ body:JSON.stringify(user), method:'POST' }); yield put({type:'query',payload:{ }}); } }, subscriptions:{ setup({ dispatch,history }){ console.log('running subscriptions ...'); return history.listen(({ pathname,search })=>{ console.log(`pathname: ${pathname}`); dispatch({ type:'query'}); }); } } }; export default User;
这里主要体现dva对redux react-saga的封装处理 一目了然了
- 然后注册model 修改路由处代码为:
import React from 'react'; import { Router, Route, Switch } from 'dva/router'; import dynamic from 'dva/dynamic'; import IndexPage from './routes/IndexPage'; function RouterConfig({ history,app }) { const UserPage=dynamic({ app, models:()=>[ import('./models/user') ], component:()=>import('./routes/usersPage') }); return ( <Router history={history}> <Switch> <Route path="/" exact component={IndexPage} /> <Route path="/users" exact component={UserPage} /> </Switch> </Router> ); } export default RouterConfig;
9.新建用户数据列表组件 使用antd的Tabel承载
顺手也把添加用户的表单建了吧

user.js
import { Table,Button } from 'antd';
import { connect } from 'dva';
import UserModal from './create';
const UserTable = ({ list,dispatch }) => {
const createUser=(user)=>{
dispatch({
type:'user/create',
payload:{
user
}
});
};
const columns=[
{
Title:'ID',
dataIndex:'id'
},
{
Title:'NAME',
dataIndex:'name'
},
{
Title:'AGE',
dataIndex:'age'
}
];
return (
<div>
<UserModal record={ {} } ok={ createUser }>
<Button type="primary">NEW</Button>
</UserModal>
<Table
columns={ columns }
dataSource={ list }
rowKey={ t=>t.id }
pagination={ false }>
{/* users datatable */}
</Table>
</div>
);
};
export default connect(({ user }) => {
console.log(user);
return {
list: user.list
};
})(UserTable);
create.js
import React,{ Component } from 'react';
import { Modal,Form,Input } from 'antd';
class UserModal extends Component{
constructor(props){
super(props);
this.state={
visible:false
};
}
render(){
const { children,form:{ getFieldDecorator },record,ok }=this.props;
const showModal=()=>{
this.setState({
visible:true
});
};
const hideModal=()=>{
this.setState({
visible:false
});
};
const save=()=>{
this.props.form.validateFields((err,val)=>{
//val ==> record
// console.log(val);
ok(val);
hideModal();
});
};
return (
<div>
<span onClick={ showModal }>
{ children }
</span>
<Modal
title="Create User"
visible={ this.state.visible }
onCancel={ hideModal }
onOk={ save }>
<Form>
<Form.Item label="Name">
{
getFieldDecorator('name', {
initialValue: record.name
})(<Input />)
}
</Form.Item>
<Form.Item>
{
getFieldDecorator('age',{
initialValue:record.age
})(<Input />)
}
</Form.Item>
</Form>
</Modal>
</div>
);
};
}
export default Form.create()(UserModal);
usersPage.js
import { connect } from 'dva';
import Main from '../components/layout/main';
import UserTable from '../components/user/user';
const UserPage=()=>{
return (
<Main>
<h1>UserPage</h1>
<UserTable />
</Main>
);
};
export default connect()(UserPage);
10.效果演示

11.源码下载
或者 https://pan.baidu.com/s/1bo1R7o7