美文网首页让前端飞Web前端之路
MobX——简单、可扩展的状态管理

MobX——简单、可扩展的状态管理

作者: 虚拟J | 来源:发表于2020-08-03 18:22 被阅读0次

    MobX 是状态管理库(侵入性最小之一),用来管理应用的内部状态。但是请注意,MobX 和 Redux 不同,只是一个解决技术问题的库,而不是状态管理容器

    MobX 通过透明的函数响应式编程使得状态管理变得简单和可扩展。

    • 灵感:来自excel表格中的反应式编程原理
    • 哲学:任何源自应用状态的东西都应该自动地获得。
    • 易操作性:相比其它状态管理解决方案,当使用 MobX 时通常只需学习更少的新概念。

    在 MobX 中使用装饰器有两种方式:

    1. 使用装饰器语法(需确保在 Babel 里配置了)
    2. 利用 MobX 内置的工具 decorate 来对类和对象进行装饰

    下面代码使用装饰器语法进行。(完整示例

    定义State

    observable 值可以是JS基本数据类型、引用类型、普通对象、类实例、数组和映射。(普通对象是指不是使用构造函数创建出来的对象,而是以 Object 作为其原型,或者根本没有原型)

    import {observable, computed} from "mobx";
    
    class ChestnutStore {
        @observable chestnuts = [];
        @computed get total() {
            return this.chestnuts.length;
        }
    }
    

    反应 是自动响应状态变化的副作用。 反应可以确保当相关状态发生变化时指定的副作用(主要是 I/O)可以自动地执行,比如打印日志、网络请求 等等

    • 使用 @observable 装饰器来给类属性添加注解,就可以简单的为数据结构添加了可观察的功能。

    MobX 不会将一个有原型的对象自动转换成 observable,因为这是构造函数的职责。
    对于非普通对象,构造函数负责初始化 observable 属性,在构造函数中使用 extendObservable 或在类定义上使用 @observable / decorate 。

    • 通过 @computed 装饰器可以定义在相关数据发生变化时自动更新的值。(自动响应状态变化的值)

    计算值有助于使实际可修改的状态尽可能的小。( 此外计算值还是高度优化过的,所以尽可能的多使用它们)

    注意计算属性是不可枚举的,它们也不能在继承链中被覆盖。

    创建视图以响应状态的变化

    import React from "react";
    import ReactDOM from "react-dom";
    import { observer } from "mobx-react";
    import { observable, computed, autorun, when, reaction } from "mobx";
    
    const store = new ChestnutStore();
    
    @observer
    class Chestnut extends React.Component {
      constructor(props) {
        super(props);
    
        this.stop = autorun(() => console.log(store.total));
        when(() => store.chestnuts.length > 10, () => alert("数量大于10了"));
        reaction(
          () => store.chestnuts.map(item => item),
          items => console.log(items.join(","))
        );
      }
      render() {
        return (
          <div>
            <ul>{store.chestnuts.map(item => item)}</ul>
            <p> Total: {store.total}</p>
            <button
              type="button"
              onClick={() => store.chestnuts.push(store.chestnuts.length)}
            >
              add
            </button>
            <button type="button" onClick={() => store.chestnuts.pop()}>
              remove
            </button>
            <button type="button" onClick={() => this.stop()}>
              终止autorun
            </button>
          </div>
        );
      }
    }
    
    • observer 函数/装饰器可以用来将 React 组件转变成响应式组件。

    它用 mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件

    • autorun 用来创建一个响应式函数,而该函数本身永远不会有观察者

    使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发。(autorun 只会观察函数运行时访问过的 observable 的状态)

    如果你有一个函数应该自动运行,但不会产生一个新的值,请使用autorun。

    autorun 返回一个清理函数用来取消副作用。

    • when 观察并运行给定的函数,直到返回值为 true。(一旦返回 true,给定的 effect 就会被执行,然后自动运行程序会被清理,也就是只会执行一次 effect 函数

    如果没提供 effect 函数,when 会返回一个 Promise 。它与 async / await 可以完美结合。

    • reaction 对于如何追踪 observable 赋予了更细粒度的控制。

    它接收两个函数参数:

    1. 第一个数据函数是用来追踪并返回数据,作为第二个副作用函数的输入。
    2. 第二个副作用函数被调用时会接收两个参数。 第一个参数是由 数据函数 返回的值。 第二个参数是当前的 reaction,可以用来在执行期间清理 reaction。(副作用函数只有在数据函数返回的数据发生更改后才会运行)

    reaction 也返回一个清理函数。不同于 autorun 的部分是,当创建函数时不会立即触发一次。

    更改状态

    除了上面代码中直接修改状态。MobX 也可以使你在代码中显式地标记出动作所在的位置。

      @action
      method() {
      //...一些逻辑
      }
    

    action.bound 可以用来自动地将动作绑定到目标对象,但不要和箭头函数一起使用,箭头函数已经是绑定过的并且不能重新绑定。

    开启“严格模式”,需要强制使用 action,不允许在 action 外更改任何状态

    configure({ enforceActions: "observed" })
    

    注意点:

    1. MobX 追踪属性访问,而不是值。例:
      如果你在 autorun 中的依赖是引用类型,而不是引用类型中某个具体属性,那么直接修改其中的数据,并不会触发 autorun 。

    一些解决方案:

    • 可以通过 mobx.toJS() 创建深克隆
    • ... 创建浅克隆
    • JSON.stringify()读取整个结构
    1. 在大型、长期的项目中,若随意的变更数据会使程序状态无法追踪,不可预测。所以建议开启 MobX 的严格模式,再加上一套状态管理的规范,让出错的可能性和找问题的成本降到最低,更方便项目的质量管理。(或者改用 redux 吧)

    参考链接:
    MobX中文文档

    相关文章

      网友评论

        本文标题:MobX——简单、可扩展的状态管理

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