阅读 987

Mobx —— React状态管理另一条路

阅读时间:大概在 3 分钟左右

本文章旨在介绍Mobx,不对其他状态管理工具进行比较。

Redux 开启了前端状态管理大门,但是对于一些比较小的应用,使用 Redux 反而增加了开发复杂度,这时候,我会选择使用 Mobx 来进行状态管理。

Mobx 是什么

Mobx是一个通过函数响应式编程,让状态管理更加简单和容易拓展的库。

它遵循一个最简单的原则:

Anything that can be derived from the application state, should be derived. Automatically.

(所有能够从应用状态获得的东西,都应该自动地被获得)

他的原理非常简洁:

mobx原理图

  • Actions 是唯一允许修改state而且有其他副作用的函数
  • State 是一组可观察的状态,而且不应该包含冗余的数据(例如不会被更新的状态)
  • Computed Value 是一些纯函数,返回通过 state 可以推导出的值
  • Reactions 类似于 Computed Value,但是它允许副作用的产生(如更新 UI 状态)

核心概念

Observable state

Mobx 为 JavaScript 本身已有的几种数据结构都添加了可观察的功能,也可以使用ES6的新特性,通过装饰器来添加这些功能。

可观察的对象:

import {observable, autorun, action} from "mobx";

var person = observable({
    // 可观察的属性
    name: "John",
    age: 42,
    showAge: false,

    // 计算后的属性
    get labelText() {
        return this.showAge ? `${this.name} (age: ${this.age})` : this.name;
    },

    // action
    setAge: action(function(age) {
        this.age = age;
    })
});
// autorun 函数是来运行状态后更新后引发的 reaction
autorun(() => console.log(person.labelText));

person.name = "Dave";
// 输出: 'Dave'

复制代码

可观察的数组:

import {observable, autorun} from "mobx";

var todos = observable([
    { title: "Spoil tea", completed: true },
    { title: "Make coffee", completed: false }
]);

autorun(() => {
    console.log("Remaining:", todos
        .filter(todo => !todo.completed)
        .map(todo => todo.title)
        .join(", ")
    );
});

todos[0].completed = false;
// 输出: 'Remaining: Spoil tea, Make coffee'

todos[2] = { title: 'Take a nap', completed: false };
// 输出: 'Remaining: Spoil tea, Make coffee, Take a nap'

todos.shift();
// 输出: 'Remaining: Make coffee, Take a nap'
复制代码

可观察的Map:

import {observable} from "mobx";

const map = observable.map();

map.set("a", 100);

console.log(map.get("a"))
// 输出: 100

map.observe(({name, newValue}) => console.log(name, "->", newValue))

map.set("b",100)
// 输出: b -> 100
复制代码

原生的值和引用:

import {observable} from "mobx";

const cityName = observable("Vienna");

console.log(cityName.get());
// 输出 'Vienna'

cityName.observe(function(change) {
    console.log(change.oldValue, "->", change.newValue);
});

cityName.set("Amsterdam");
// 输出 'Vienna -> Amsterdam'
复制代码

Actions

状态管理中有一个重要的概念,状态应该以一种方式来更新。在Mobx之中,并不需要触发事件、调用分发函数或者类似的动作,状态的基本相应派发由 Mobx 本身来负责。

但是让Mobx全盘接管显然限制了可拓展性和可用性,所以Mobx提供了Actions来使用。Actions应该永远只对修改状态的函数使用动作。建议对任何修改 observables 或具有副作用的函数使用 (@)action 。 结合开发者工具的话,动作还能提供非常有用的调试信息。

Reactions

Reactions 和计算值很像,但它不是产生一个新的值,而是会产生一些副作用,比如打印到控制台、网络请求、递增地更新 React 组件树以修补DOM、等等。 简而言之,reactions 在 响应式编程和命令式编程之间建立沟通的桥梁。

在 React 里使用 Mobx

谈了那么多概念那么怎么在 React 里面使用呢。

observer 函数/装饰器可以用来将 React 组件转变成响应式组件。 它用 mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。 observer 是由单独的 mobx-react 包提供的。

import {observer} from "mobx-react";

var timerData = observable({
    secondsPassed: 0
});

setInterval(() => {
    timerData.secondsPassed++;
}, 1000);

@observer class Timer extends React.Component {
    render() {
        return (<span>Seconds passed: { this.props.timerData.secondsPassed } </span> )
    }
};

React.render(<Timer timerData={timerData} />, document.body);
复制代码

mobx 使用的时候,确保让observer渗透到最深处的组件,因为状态是向下传递的,如果原子组件没有加入Mobx的观察,那么就可能就没有效果。

拓展阅读

官方文档

十分钟交互式的 MobX + React 教程

访谈: 状态管理很容易 - React Amsterdam 2016 开发者大会 (幻灯片)

关注下面的标签,发现更多相似文章
评论