用dvaJS实现todolist(增删改)
效果图




这几天在看dvaJS,dva 首先是一个基于 redux和 redux-saga的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router和 fetch,所以也可以理解为一个轻量级的应用框架。
要想学好dva你要对ES6有一些了解,对React有些了解,上手的时候就比较容易。
写这个todolist首先得安装dva-cli
通过npm安装dva-cli
npm install dva-cli -g
安装完成后输入dva -v查看版本号
创建新应用
安装完dva-cli后,可以在命令行访问到dva命令
通过dva new dva-quickstart创建新应用
这会创建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

浙公网安备 33010602011771号