mobx的使用

MobX

简单、可扩展的 JavaScript 状态管理库。一般和 React 结合使用。

安装

浏览器支持

  • MobX>=5 版本可运行在任何支持 es6 的浏览器中,不支持 IE11 以下和 Node 5 以下。
  • MobX 4 可以运行在任何支持 ES5 的浏览器上,而且也在持续的维护中,但是 MobX4 具有一些局限性,长期维护支持版。

入门

MobX 通过透明的函数响应式编程使得状态管理变得简单和可扩展。MboX 的核心思想就是:

任何源自应用状态的东西都应该自动地获得。

其中包括 UI、数据序列化、服务器通讯等等。

MobX unidirectional flow

在 React 中使用 MobX。React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而 MobX 提供机制来存储和更新应用状态供 React 使用(类似于 Vue 中的 Vuex)。

MobX 提供了优化应用状态于 React 组件同步的机制,这种机制就是使用响应式虚拟依赖状态图表,它只有在真正需要的时候才更新并且永远保持是最新的。

装饰器

装饰器是一个对类进行处理的函数

  • 基本语法

    @xxx

  • 返回函数为装饰器传参

    @xxx(value)

  • 添加实例属性

    mixin

@fn //基本语法
@fn2(20) //传参
@fn3 //添加实例属性
class Myclass {
  @readonly message = "hello";
  @noenumerable bar = "foo";
  @noenumerable test() {
    console.log("hello,test");
  }
}

function fn(target) {
  target.foo = "bar";
}

function fn2(value) {
  return function (target) {
    target.count = value;
  };
}

function fn3(target) {
  target.prototype.foo = "baz";
}
//设置只读
function readonly(target, name, descriptor) {
  /*   console.log(target); //目标类的.prototype
  console.log(name); //被修饰的类成员的名称
  console.log(descriptor); // 被修饰的类成员的描述对象 */
  descriptor.writable = false;
}
//不可被遍历
function noenumerable(target, name, descriptor) {
  // descriptor.enumerable = false;
}

const c1 = new Myclass();
// console.log(c1.message);
for (let key in c1) {
  console.log(key, c1[key]);
}
c1.test();
/* console.log(Myclass.foo);
console.log(Myclass.count);
console.log(new Myclass().foo); */

核心 API

其中 observablecomputedreactions 和 action是 MobX 最重要的 API

MObX

改变 observables

observable

Observable 值可以是 JS 基本数据类型、引用类型、普通对象、类实例、数组和映射。

@observable count = 0;
@observable foo = 'bar';

observer

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

@observer
class App extends React.Component {}

computed

根据现有的状态或其它计算值衍生出的值,在多从调用 computed 方法时,计算属性的方法只执行一次,因为它会缓存计算方法,除非方法中的属性改变。用于返回数据。

@computed get totalPrice() {
    return this.price * this.count;
}

action

只对修改状态的函数使用动作。配置 mobx 强制使用 action,通过 configure 中的 enforceActions 配置为 observed,不容许在 action 之外修改容器状态。自我认为类似于 React 中的 setState。

configure({
  enforceActions: "observed",
});

action.bound

为方法绑定 this。一般情况下 action 都与 bound 连用。

@action.bound change() {
    console.log(this);
    this.count = 10;
    this.foo = 'hello';
    this.foo = 'world';
 }

action-runInAction

在不想调用 action 函数时,可以直接使用 runInAction 来改变属性的值。

runInAction(() => {
  this.count = 100;
});

异步 action

在 action 严格模式下无法直接修改容器中属性的状态,可通过

  1. 定义 action 函数使用
  2. 直接调用 action 函数
  3. runInAction
@action.bound asyncChange() {
    setTimeout(() => {
      // this.count = 100;
      // 1. 定义 action 函数
      // this.changeCount()
      // 2. 直接调用action函数
      // action('changeFoo',()=>{
      //   this.foo ='hello'
      // })()
      // 3. runInAction
      runInAction(() => {
        this.count = 100;
      });
    }, 100);
  }

when

当依赖的数据条件被满足时触发,只执行一次,之后不再处理。如果第一次条件被满足就会被立刻执行。

// 当 count > 100 的时候,只执行一次自定义逻辑when(  () => {    return store.count > 100;  },  () => {    console.log('when=> ', store.count);  });

reaction

reaction 只有当被观测的数据发生改变的时候,才会执行,reaction 可频繁触发。

reaction(  () => {    // 执行一些业务逻辑操作,返回数据给下一个函数使用。    return store.count;  },  (data, reaction) => {    console.log('reaction=> ', data);    // 手动停止当前 reaction的监听    reaction.dispose();  });

学习排坑

目前直接使用 npm i mobx mobx-react 时,mobx 下载的版本是 6,目前官方文档还没有更新,所以在下载依赖时,建议在 mobx 后加@5.15.5 这种具体版本号。

mobx-react

import { observer, Provider, inject } from "mobx-react";

Provider

Provider 是一个 React 组件,使用 React 的上下文(context)机制,可以用来向下传递 stores,即把 state 传递给其子组件。

const stores = { mainStore, userStore, commonStore };
ReactDOM.render(
  <Provider {...stores}>
    {" "}
    <App />{" "}
  </Provider>,
  document.getElementById("container")
);

inject

inject 是一个高阶组件,作用是将组件连接到提供的 stores。具体说是与 Provider 结合使用,从 Provider 提供给应用的 state 数据中选取所需数据,以 props 的形式传递给目标组件。

@inject( 'userStore')@observerexport default class User extends Component{}