4
MobX用于简单、可扩展的React状态管理,相比Redux有更高的灵活性,文档参考:MobX中文文档,本文作为入门,介绍一个简单的TodoList项目。

1. 预期效果

图片描述
项目机构:
图片描述

2. 项目搭建

  • Step1: npx create-react-app my-app 创建项目;
  • Step2: npm install mobx mobx-react --save-dev 安装 mobx 的相关依赖;
  • Step3: npm run eject使create-react-app 创建的项目支持装饰器语法;
  • Step4: npm install @babel/plugin-proposal-decorators --save-dev安装装饰器
  • Step5: 修改package.json文件:
"babel": {
    "plugins": [
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ]
    ],
    "presets": [
      "react-app"
    ]
  },

3. 创建TodoListStore

Mobx 中创建 store 的常见关键字如下: observable, computed, action

import { observable, action, computed } from 'mobx'

class Todo {
    id = Math.random();
    @observable title;
    @observable finished = false;

    constructor(title) {
        this.title = title
    }
}

class TodoList {
    @observable todos = [];

    @computed get completedTodosCount() {
        return this.todos.filter(todo => todo.finished).length;
    }

    @computed get report() {
        if (this.todos.length === 0) 
            return "任务已完成"
        return `下一个任务:${this.todos[0].title}`
    }

    @action addTodo (title) {
        if (!title) return;
        this.todos.push(new Todo(title));
    }
}
const store = new TodoList();
store.todos.push(new Todo('修复谷歌浏览器页面显示问题'), new Todo('提交意见反馈代码'));
store.todos[1].finished = true;

export default store;

4. 创建TodoListView

import React, {Component} from 'react';
import {observer, inject} from 'mobx-react';

const TodoView = ({todo}) => (
    <li>
        <input 
            type="checkbox" 
            checked={todo.finished} 
            onChange={() => {todo.finished = !todo.finished;}} 
        />
        {todo.title}
    </li>
)
@inject('TodoListStore')

@observer
class TodoListView extends Component {
    constructor(props) {
      super(props);
      this.state = {
          title: ''
      }
    }

  changeTitle = e => {
      let title = e.target.value;
      this.setState({title});
  }

  submit = () => {
      this.props.TodoListStore.addTodo(this.state.title);
  }

  render() {
      return (
          <div>
              <input type="text" value={this.state.title} onChange={this.changeTitle} />
        <button onClick={this.submit}>submit</button>
        <ul>
            {this.props.TodoListStore.todos.map(todo => (
                <TodoView todo={todo} key={todo.id} />
            ))}
        </ul>
        Tasks finished: {this.props.TodoListStore.completedTodosCount}
          </div>
      );
  }
}
export default TodoListView

5. 在App.js中引入TodoListView

import React, { Component } from 'react';
import './App.css';
import TodoListStore from "./components/todolist/store/TodoListStore";
import TodoListView from "./components/todolist/index";
import { Provider } from 'mobx-react';

export default class App extends Component {

  render() {
    return (
      <Provider TodoListStore={TodoListStore}>
        <TodoListView/>
      </Provider>
    )
  }
}

6. 主入口文件src/index.js设置

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App/>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

参考:


芒果屋里的猫
2.3k 声望363 粉丝

同步 -> 异步 -> 回调