美文网首页
使用dva实现TodoList

使用dva实现TodoList

作者: 小m_up | 来源:发表于2018-03-05 19:22 被阅读597次

    刚刚接触dva,因为它是 reduxredux-sagareact-router的轻量级前端框架,之前用过reduxreact-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的很容易懂的,所以在这我就不多解释了

    代码地址:https://github.com/yangzhanmei/dva-todoList-demo

    相关文章

      网友评论

          本文标题:使用dva实现TodoList

          本文链接:https://www.haomeiwen.com/subject/ojzgxftx.html