效果圖css
這幾天在看dvaJS,dva 首先是一個基於 redux和 redux-saga的數據流方案,而後爲了簡化開發體驗,dva 還額外內置了 react-router和 fetch,因此也能夠理解爲一個輕量級的應用框架。html
要想學好dva你要對ES6有一些瞭解,對React有些瞭解,上手的時候就比較容易。react
寫這個todolist首先得安裝dva-cligit
經過npm安裝dva-cligithub
npm install dva-cli -g npm
安裝完成後輸入dva -v查看版本號redux
建立新應用服務器
安裝完dva-cli後,能夠在命令行訪問到dva命令antd
經過dva new dva-quickstart建立新應用react-router
這會建立dva-quickstart目錄,包含項目初始化目錄和文件,並提供開發服務器、構建腳本、數據mock服務、代理服務器等功能。
而後咱們cd進入dva-quickstart目錄,並啓動開發服務器
cd dva-quickstart
npm start
components模塊
add.js
import React, { Component } from 'react' import { Form, Input, Button, Select } from 'antd' import { connect } from 'dva' import styles from './input.css' const { Option } = Select; class Add extends Component { render() { const { getFieldDecorator } = this.props.form return ( <div> <Form onSubmit={this.handleAdd} className={styles.form}> <Form.Item label="姓名" className={styles.formItem}> {getFieldDecorator('name', { rules: [ { required: true, message: '不能爲空' }, { pattern: /^[\u4E00-\u9FA5\uf900-\ufa2d·s]{2,20}$/, message: '輸入中文名字' } ] })(<Input width='100' />)} </Form.Item> <Form.Item label="年齡" className={styles.formItem}> {getFieldDecorator('age', { rules: [ { required: true, message: '不能爲空' }, { pattern: /^(?:[1-9][0-9]?|1[01][0-9]|120)$/, message: '請輸入年齡' } ] })(<Input width='100' />)} </Form.Item> <Form.Item label="學歷" className={styles.formItem}> {getFieldDecorator('xl', { rules: [ { required: true, message: '不能爲空' } ] })( <Select style={{ width: 184 }}> <Option value="本科">本科</Option> <Option value="碩士">碩士</Option> <Option value="博士">博士</Option> <Option value="專科">專科</Option> </Select> )} </Form.Item> <Form.Item className={styles.formItem}> <Button htmlType="submit" type="primary">添加</Button> </Form.Item> </Form> </div> ) } handleAdd = (e) => { e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { //與後臺進行數據交互 const list = {} list.name = values.name list.age = values.age list.xl = values.xl this.props.form.setFieldsValue({ name: '', age: '', xl: '' })//點擊肯定讓input輸入框中的值爲空 this.props.dispatch({ type: 'todo/add', payload: list }) } }) } } const mapStateToProps = (state) => { return { list: state.todo.list } } export default connect(mapStateToProps)(Form.create()(Add))
modify.js
import React, { Component } from 'react' import { Form, Input, Button,Select } from 'antd' import { connect } from 'dva' import styles from './input.css' const {Option} = Select class Add extends Component { render() { console.log(this.props) let { list, toIndex } = this.props const todoList = list[toIndex] const { getFieldDecorator} = this.props.form return ( <div> <Form onSubmit={this.handleUpdate} className={styles.form}> <Form.Item label="姓名" className={styles.formItem}> {getFieldDecorator('name', { initialValue:todoList.name,//設置初始的值 rules: [ { required: true, message: '不能爲空' }, { pattern: /^[\u4E00-\u9FA5\uf900-\ufa2d·s]{2,20}$/, message: '輸入中文名字' } ] })(<Input/>)} </Form.Item> <Form.Item label="年齡" className={styles.formItem}> {getFieldDecorator('age', { initialValue:todoList.age, rules: [ { required: true, message: '不能爲空' }, { pattern: /^(?:[1-9][0-9]?|1[01][0-9]|120)$/, message: '請輸入年齡' } ] })(<Input/>)} </Form.Item> <Form.Item label="學歷" className={styles.formItem}> {getFieldDecorator('xl', { initialValue:todoList.xl, rules: [ { required: true, message: '不能爲空' } ] })( <Select style={{ width: 184 }}> <Option value="本科">本科</Option> <Option value="碩士">碩士</Option> <Option value="博士">博士</Option> <Option value="專科">專科</Option> </Select> )} </Form.Item> <Form.Item className={styles.formItem}> <Button htmlType="submit" type="primary">修改</Button> </Form.Item> </Form> </div> ) } handleUpdate = (e) => { e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { //與後臺進行數據交互 const list = {} list.name = values.name list.age = values.age list.xl = values.xl this.props.form.setFieldsValue({name:'',age:'',xl:''})//點擊肯定讓input輸入框中的值爲空 this.props.dispatch({ type:'todo/update', payload:list }) } }) } } const mapStateToProps = (state) => { return { list: state.todo.list, toIndex: state.todo.toIndex } } export default connect(mapStateToProps)(Form.create()(Add))
list.js
import React, { Component } from 'react' import { connect } from "dva" import { Button } from 'antd' import styles from './input.css' class List extends Component { render() { let { list } = this.props return ( <div> { list ? list.map((item, index) => ( <li key={index} className={styles.list}> <div> <span>姓名------{item.name}</span><br /> <span>年齡------{item.age}</span><br /> <span>學歷------{item.xl}</span> <br /> </div> <div className={styles.btn}> <Button htmlType='submit' type='primary' onClick={() => this.handleModify(index)}>修改</Button> <Button htmlType='submit' type='danger' onClick={() => this.handleDelete(index)}>刪除</Button> </div> </li> )) : '' } </div> ) } handleModify(index) { this.props.dispatch({ type: 'todo/modify', payload: index }) } handleDelete(index) { this.props.dispatch({ type: 'todo/delete', payload: index }) } } const mapStateToProps = (state) => { return { list: state.todo.list } } export default connect(mapStateToProps)(List)
routes模塊(至關於pages)
input.js
import React, { Component } from 'react' import Add from "../components/add" import ListTo from './list' import Modify from "../components/modify" import {connect} from 'dva' class InputList extends Component { render() { let {flag} = this.props return ( <div> { flag? <Add/>:<Modify/> } <ListTo/> </div> ) } } const mapStateToProps=(state)=>{ return { flag:state.todo.flag } } export default connect(mapStateToProps)(InputList)
models模塊
input.js
import queryString from 'query-string'; import { add } from '../services/todolist' export default { namespace: 'todo', state: { list: [], flag:true, toIndex:'' }, subscriptions: { setup({ dispatch, history }) { history.listen(location => { }) } }, effects: { *add({ payload: value }, { call, put, select }) { const data = yield call(add, value) let templist = yield select(state => state.todo.list) let list = [] list = list.concat(templist) const tempObj = {}; tempObj.name = value.name tempObj.age = value.age tempObj.xl = value.xl list.push(tempObj) yield put({ type: 'updateState', payload: { list } }) }, *delete({ payload: index }, { call, put, select }) { const data = yield call(add, index) let templist = yield select(state => state.todo.list) let list = [] list = list.concat(templist) list.splice(index, 1) yield put({ type: 'updateState', payload: { list } }) }, *modify({payload:index},{call,put,select}){ const data = yield call(add,index) let templist = yield select(state => state.todo.list) let list = [] list = list.concat(templist) yield put({ type: 'updateState', payload: { flag:false,list,toIndex:index } }) }, *update({payload:value},{call,put,select}){ const data = yield call(add,value) let templist = yield select(state => state.todo.list) let toIndex = yield select(state => state.todo.toIndex) let list = [] list = list.concat(templist) list.splice(toIndex,1,value) yield put({ type: 'updateState', payload: { flag:true,list } }) }, }, reducers: { updateState(state, action) { return { ...state, ...action.payload } } }, }
在根目錄下的index.js裏註冊一下models
一樣是在根目錄下的router.js裏註冊路由
歡迎評論,共同交流,一塊兒進步
源碼連接:gitHub