Mobx 初探

PeterYuan發表於2019-03-03

什麼是Mobx

官網 github-mobx

MobX 是一個經過戰火洗禮的庫,
它通過透明的函式響應式程式設計
(transparently applying functional reactive programming - TFRP)
使得狀態管理變得簡單和可擴充套件。
複製程式碼

pic

更多詳細介紹,請移步官網細閱。

為什麼使用Mobx

React 和 MobX 是一對強力組合。React 通過提供機制把應用狀態轉換為可渲染元件樹並對其進行渲染。而MobX提供機制來儲存和更新應用狀態供 React 使用。 ——官方文件

可能我們都比較熟悉Redux,簡而言之Mobx是比Redux更有力的和React結合使用的助手。

如何使用

下面我們就用一個例子簡單的使用Mobx——ToDOList. Talking is cheap, show me your code! 程式碼地址 由於沒有和parcel使用初探的程式碼分離,所以,希望你也能看的明白

編輯器

VSCode

編輯器配置

為了使用Es.next的裝飾器語言@,需要配置VsCode,具體——如何(不)使用裝飾器

vscode setup

依賴

//package.json file setup:
  "dependencies": {
    "mobx": "^3.4.1",
    "mobx-react": "^4.3.5",
    "react": "^16.2.0",
    "react-dom": "^16.2.0"
    }
複製程式碼
//package.json file setup:
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-1": "^6.24.1",
    "mobx-react-devtools": "^4.2.15",
    }
複製程式碼

配置

//.babelrc file setup:
{
  "presets": [
    "env",
    "react",
    "es2015",
    "stage-1"
  ],
  "plugins": [
    "transform-decorators-legacy"
  ]
}
複製程式碼

程式碼

store 建立

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


class toDo {
  id = Math.random();
  @observable title = '';
  @observable completed = false;
}

class todoStore {
  @observable todos = [];

  @computed get completedCount() {
    return this.todos.filter(todo => todo.completed).length;
  }
  
  @computed get totalCount() {
    return this.todos.length;
  }

  @action.bound toggleCompleted(id) {
    this.todos.forEach(todo => {
      if (todo.id === id) todo.completed = !todo.completed;
    })
  }

  @action.bound addToDo(title) {
    if (!title) return alert('please input something...');
    let todo = new toDo();
    todo.title = title;
    this.todos.push(todo);
  }
};

const store = new todoStore();

export { store }
複製程式碼

ToDo元件

import React, { Component } from 'react';
import { observer } from "mobx-react";
import { store } from '../../store'
import './style.css'

@observer export default class ToDo extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { title, id, completed } = this.props;
    return (<div
      className={`todo ${completed ? 'completed' : ''}`}
      onClick={() => store.toggleCompleted(id)}
    >
      {title}
    </div>);
  }
}
//style.css
.todo{
  background-color: white;
  text-align: center;
  font-size: 30px;
  margin: 3px;
}

.todo.completed{
  background-color: brown;
}
複製程式碼

App.js

import React, { Component } from 'react'
import { observer } from "mobx-react";
import DevTools from 'mobx-react-devtools'
import ToDo from './components/ToDo'
import { store } from './store'


const TEXT = 'please input something...';
const ToDoList = ({ todos }) => todos.map(t => <ToDo key={t.id} {...t} />);

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

  render() {
    const { title } = this.state;
    const { todos, totalCount, completedCount } = store;
    return (<div className="APP">
      <input
        style={{ width: 300 }}
        placeholder={TEXT}
        value={title}
        onChange={e => this.setState({ title: e.currentTarget.value })}
      />
      <button onClick={() => {
        store.addToDo(title);
        this.setState({ title: '' });
      }}>Add one ToDo</button>
      <div>{`total count:${totalCount}`}</div>
      <div>{`total completed count:${completedCount}`}</div>
      <ToDoList todos={todos} />
      <DevTools />
    </div>);
  }
}
複製程式碼

效果圖

show