刚刚接触dva
,因为它是 redux
、redux-saga
和react-router
的轻量级前端框架,之前用过redux
和react-router
,所以就了解了一下redux-saga
,发现其实和之前用的thunk
挺像的,然后看完redux-saga
再使用dva
,你就会发现,dva
真的是太方便了,好了,废话不多说了,那么就来开始写代码叭
- 安装 dva-cli
npm install dva-cli -g
- 初始化项目
dva new dva-todoList-demo
此时你打开 http://localhost:8000 ,你会看到 dva
的欢迎界面。
- 编写component/TodoList.js组件
import React from 'react';
class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {value: ""};
}
addTodo(e) {
if (e.keyCode === 13) {
const todo = e.target.value;
this.props.dispatch({
type: 'todos/addTodo',
payload: todo
});
this.setState({value: ''})
}
}
deleteTodo(index) {
this.props.dispatch({
type: 'todos/deleteTodo',
payload: index
})
}
toggleItem(index) {
this.props.dispatch({
type: 'todos/toggle',
payload: index
})
}
modifyTodo(e, index) {
this.props.dispatch({
type: 'todos/modifyTodo',
payload: {index, todo: e.target.value}
})
}
render() {
const todoList = this.props.todoList.map((val, index) => {
return <div key={index}>
<input type="checkbox"
checked={val.finished}
onChange={() => this.toggleItem(index)}/>
< input value={val.value}
onChange={(e) => this.modifyTodo(e, index)}
autoFocus={false}
/>
<button onClick={() => this.deleteTodo(index)}>X</button>
</div>
});
let count = 0;
this.props.todoList.map(item => count = !item.finished ? count + 1 : count);
return (
<div>
<h3>待办事项有:{count}</h3>
<input placeholder="please input"
value={this.state.value}
onChange={(e) => this.setState({value: e.target.value})}
onKeyDown={(e) => this.addTodo(e)}/>
<div>
{todoList}
</div>
</div>
)
}
}
export default TodoList;
- 编写routes/Todos.js
import React from 'react';
import {connect} from 'dva';
import TodoList from '../components/TodoList';
const mapStateToProps = (state) => {
return {
todoList: state.todos.todoList
}
};
export default connect(mapStateToProps)(TodoList);
- 修改router.js并在里面引入Todos的路由
...
import Todos from './routes/Todos';
...
<Route path="/todos" exact component={Todos}/>
...
- 编写models/todos.js
import queryString from 'query-string';
import * as todoService from '../services/todo'
export default {
namespace: 'todos',
state: {todoList: []},
reducers: {
save(state, {payload: {todoList}}) {
return {...state, todoList}
}
},
effects: {
* addTodo({payload: value}, {call, put, select}) {
// 模拟网络请求
const data = yield call(todoService.query, value);
let tempList = yield select(state => state.todos.todoList);
let todoList = [];
todoList = todoList.concat(tempList);
const tempObj = {};
tempObj.value = value;
tempObj.id = todoList.length;
tempObj.finished = false;
todoList.push(tempObj);
yield put({type: 'save', payload: {todoList}})
},
* deleteTodo({payload: index}, {call, put, select}) {
const data = yield call(todoService.query, index);
let tempList = yield select(state => state.todos.todoList);
let todoList = [];
todoList = todoList.concat(tempList);
todoList.splice(index, 1);
yield put({type: 'save', payload: {todoList}})
},
* toggle({payload: index}, {call, put, select}) {
const data = yield call(todoService.query, index);
let tempList = yield select(state => state.todos.todoList);
let todoList = [];
todoList = todoList.concat(tempList);
let obj = todoList[index];
obj.finished = !obj.finished;
yield put({type: 'save', payload: {todoList}})
},
* modifyTodo({payload: {index, todo}}, {call, put, select}) {
const data = yield call(todoService.query, {index, todo});
let tempList = yield select(state => state.todos.todoList);
let todoList = [];
todoList = todoList.concat(tempList);
let obj = todoList[index];
obj.value = todo;
yield put({type: 'save', payload: {todoList}})
},
},
subscriptions: {
setup({dispatch, history}) {
// 监听路由的变化,请求页面数据
return history.listen(({pathname, search}) => {
const query = queryString.parse(search);
let todoList = [];
if (pathname === 'todos') {
dispatch({type: 'save', payload: {todoList}})
}
})
}
}
};
那么此时你打开http://localhost:8000/#/todos就可以使用啦
只是写了简单的实现,没有添加样式,代码可以自己看一下,学过redux
的很容易懂的,所以在这我就不多解释了
网友评论