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