美文网首页
mobx实现todoList

mobx实现todoList

作者: any_5637 | 来源:发表于2019-11-07 13:59 被阅读0次

    在了解mobx的基础之后,今天写了一个小demo,实现todolist。

    开发环境搭建

    1. 创建项目: npx create-react-app mobx-todo;
    2. 安装mobx相关依赖:npm install -S mobx mobx-react;
    3. 安装项目支持装饰器的依赖:
      npm run eject
      npm install --save-dev babel-plugin-transform-decorators-legacy
    4. 在根目录下创建.babelrc文件并写入:
      {
        "presets": ["@babel/preset-env"],
        "plugins": [
          ["@babel/plugin-proposal-decorators", { "legacy": true }],
          ["@babel/plugin-proposal-class-properties", { "loose": true }]
        ]
      }
    
    1. 启动服务器:npm run start

    创建mobx状态管理store

    在根目录下创建文件夹stores,新建store.js文件,声明一个类todoList,给其创建属性:todos,使用@observable让其变为可观察对象,其中操作的过程就不细说,先上代码:

      import {observable, action, computed, toJS} from 'mobx';
    
      class todoList {
        @observable todos = [
            {
              id: parseInt(Math.random() * 10000000),
              isComplete: false,
              title: 'ddd'
            },
            {
              id: parseInt(Math.random() * 10000000),
              isComplete: true,
              title: 'ddd'
            }
          ];
    
        // 计算属性,重可观察属性 todos 衍生出来,返回没有完成的待办项的个数
        @computed get unfinishedTodoCount() {
            return this.todos.filter(todo => !todo.isComplete).length;
        }
    
        // 计算属性,重可观察属性 todos 衍生出来,返回已完成的待办项的个数
        @computed get finishedTodoCount() {
            return this.todos.filter(todo => todo.isComplete).length;
        }
    
        @action
        toggleComplete = (val) => {
          const todos = toJS(this.todos).map(item => {
            if(item.id == val) {
              item.isComplete=true;
            }
            return item;
          });
          this.todos = todos;
        }
    
        @action
        toggleTodo = (val) => {
          const todos = toJS(this.todos).map(item => {
            if(item.id == val) {
              item.isComplete=false;
            }
            return item;
          });
          this.todos = todos;
        }
    
        @action
        AddTodo = (val) => {
          const todo = this.todos;
          this.todos = [val, ...todo];
        }
    
        @action
        deletes = (val) => {
          const todos = toJS(this.todos).filter(item => item.id != val);
          this.todos = todos;
        }
    
      }
    
    
      const store = new todoList();
      export default store;
    

    实现监听数据的组件

    Provider、observer、inject均为是mobx-react提供。
    Provider以组件的形式存在,用来包裹最外层组件节点,并且传入 store(通过)context 传递给后代组件。
    使用@observer装饰的react组件将转换成一个监听者,当@observable 修饰的数据变化,react组件就会重新渲染。
    @inject为了使被装饰的组件以 props 的形式获取到 Provider 传递过来的数据。
    新建三个组件AddTodo.js Done.js Todo.js,在组件中使用this.props获得父组件的stores数据。
    AddTodo组件:新增待办事项

      import React from 'react';
      import {observer, inject} from 'mobx-react';
      import './AddTodo.css';
      @inject('appState')
      @observer
      export default class AddTodo extends React.Component {
          constructor(props) {
            super(props);
            this.state = {
              input: '', // 定义新增事项的输入框的值
            }
          }
          // 监听输入框的值
          handleInput(e) {
            this.setState({
              input: e.target.value
            })
          }
          // 确认新增,调用store的动作,新增数据
          handleClick(e) {
            this.props.appState.AddTodo({
              id: parseInt(Math.random() * 10000000),
              isComplete: false,
              title: this.state.input
            });
            this.setState({
              input: ''
            }); // 清空输入框数据
          }
          render() {
            return (
              <div className='input-box'>
                <input value={this.state.input} onChange={(e)=>this.handleInput(e)}></input><button onClick={(e)=>this.handleClick(e)}>确认</button>
              </div>
            )
          }
      }
    

    Todo组件:展示正在进行的事项

      import React, { Component } from 'react';
      import {observer, inject} from 'mobx-react';
      import './Todo.css';
      @inject('appState')
      @observer
      export default class Todo extends Component {
        constructor(props) {
            super(props);
        }
        // 改变事项的状态为已完成
        todoChange = (event) => {
            //当onChange事件发生时,调用toggleComplete动作
            this.props.appState.toggleComplete(event.target.value);
        }
        //取得未完成的todo数量
        // getUnfinishedCount() {
        //   return this.props.appState.todos.filter((i) => {
        //     return i.isComplete === false;
        //   }).length;
        // }
        // 删除数据
        deletee = (event) => {
          this.props.appState.deletes(event.target.getAttribute("data-id"));
        }
        getTodos() {
          return this.props.appState.todos.map((todo, index) => {
            if(todo.isComplete == false) {
              return (<li key={index} className='ulli'>
                <input type="checkbox" value={todo.id} checked={todo.isComplete} onChange={this.todoChange}/> 
                    <span>{todo.title}</span>
                <button type="button" data-id={todo.id} onClick={this.deletee}>删除</button>
              </li>)
            }
          });
        }
        render() {
          console.log( this.props.appState.todos)
          return (<div className='ising'>
              <h5>正在进行<span className='ingspan'>{this.props.appState.unfinishedTodoCount}</span></h5>
            <ul className='ullist'>
              {this.getTodos()}
            </ul>
          </div>);
        }
      }
    

    Done组件:展示已完成的事项

      import React from 'react';
      import {observer, inject} from 'mobx-react';
    
      @inject('appState')
      @observer
      export default class Done extends React.Component {
        constructor(props) {
          super(props);
        }
        todoChange = (event) => {
          this.props.appState.toggleTodo(event.target.value);
        }
        //取得已经完成的todo数量
        // getUnfinishedCount() {
        //   //this.props.todos就是从connect传入的state数据
        //   return this.props.appState.todos.filter((i) => {
        //     return i.isComplete === true;
        //     }).length;
        // }
        // 删除已完成事项
        delete = (event) => {
          this.props.appState.deletes(event.target.getAttribute("data-id"))
        }
        getTodos() {
          return this.props.appState.todos.map((todo, index) => {
            if(todo.isComplete == true) {
              return (<li key={index} className='ulli'>
                <input type="checkbox" value={todo.id} checked={todo.isComplete} onChange={this.todoChange}/> 
                  <del>{todo.title}</del>
                <button type="button" data-id={todo.id} onClick={this.delete}>删除</button>
              </li>)
            }
          });
        }
        render() {
          return (<div className='ising'>
              <h5>已经完成<span className='ingspan'>{this.props.appState.finishedTodoCount}</span></h5>
            <ul className='ullist'>
              {this.getTodos()}
            </ul>
          </div>);
        }
      }
    

    通过 Provider 将数据传递给组件树

    在app.js中,引入store,并通过Provider酱紫组件包裹,把store的数据传给子组件。

      import React from 'react';
      import ReactDOM from 'react-dom';
      import './App.css';
      import Todo from './views/Todo.js';
      import AddTodo from './views/AddTodo.js';
      import Done from './views/Done.js';
      import store from './stores/store.js';
      import {Provider} from 'mobx-react';
    
      ReactDOM.render(
        <div className='box'>
          <Provider appState={store}>
            <AddTodo></AddTodo>
            <Todo></Todo>
            <Done></Done>
          </Provider>
        </div>,
        document.getElementById('app')
      );
    

    实现效果:


    20191107_134916.gif

    相关文章

      网友评论

          本文标题:mobx实现todoList

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