知识沉淀--Mobx

170 阅读3分钟

Mobx

mobx是什么


Mobx是一个状态管理工具(类似于redux、vuex),通过透明的函数响应编程使得状态管理变得很简单与可扩展

Mobx原理

事件触发了 Actions,Actions 作为唯一修改 State 的方式,修改了 State,State 的修改更新了计算值 Computed,计算值的改变引起了 Reactions 的改变,导致了 UI 的改变,Reactions 可以经过事件调用 Actions。

Mobx的核心


@observable:在类中定义响应式对象

@action:在类中定义响应式相关方法,使用action.bound在此基础上对this指向进行了绑定,永远指向实例

@computed:计算属性,同vue中的计算属性相同,具有缓存功能

@observe:捕捉react组件中的内容变化

@inject:在react组件中注入store到props中

监视数据变化

autorun函数:默认执行一次,之后当内部所依赖的数据发生改变时重新触发执行

when函数:两个参数均为函数,第一个参数是设置的执行条件,第二个参数当满足第一个参数条件时的执行函数,不管后续变化是否满足都仅触发一次执行函数

reaction函数:两个参数均为函数,参数一:执行业务逻辑操作,第二个参数函数(data,reaction)有两个参数,第一个参数是一个参数函数的返回值,可以通过第二参数手动停止监听(reaction.dispose)

reaction与autorun的区别为,没有默认执行一次,可以手动停止监听

如何使用Mobx


Mobx6.0相比于之前有了极大的简化,可以说更加好用了。之前的版本是装饰器风格的语法糖,但是装饰器在现在的 ES 规范中并不成熟,而且引入装饰器语法也在增加打包后的代码体积。综合考虑后,MobX 6.0 取消了装饰器语法的 API。

响应式对象

MobX 通过 makeObservable 方法来构造响应式对象,传入的对象属性会通过 Proxy 代理,与 Vue 类似,在 6.0 版本之前使用的是 Object.defineProperty API,当然 6.0 也提供了降级方案。

6.0之前的装饰器语法

class Store {
  @observable count = 0
  constructor() {
    makeObservable(this)
  }
  @action increment() {
    this.count++;
  }
  @action decrement() {
    this.count--;
  }
  @computed get double() {
    return this.count * 2
  }
}
​
const store = new Store()

6.0之后使用makeObservable构建响应式对象

import { configure, makeObservable, observable, action, computed } from 'mobx'// 使用该配置,可以将 Proxy 降级为 Object.defineProperty
configure({ useProxies: "never" });
​
// 构造响应对象
const store = makeObservable(
  // 需要代理的响应对象
  {
    count: 0,
    get double() {
      return this.count * 2
    },
    increment() {
      this.count += 1
    },
    decrement() {
      this.count -= 1
    }
  },
  // 对各个属性进行包装,用于标记该属性的作用
  {
    count: observable, // 需要跟踪的响应属性
    double: computed,  // 计算属性
    increment: action, // action 调用后,会修改响应对象
    decrement: action, // action 调用后,会修改响应对象
  }
)

简化的6.0版本语法,依赖于makeAutoObservable,makeAutoObservable 是一个更强大的 makeObservable,可以自动为属性加上对象的包装函数。

import { makeAutoObservable } from 'mobx'const store = makeAutoObservable({
  count: 0,
  get double() {
    return this.count * 2
  },
  increment() {
    this.count += 1
  },
  decrement() {
    this.count -= 1
  }
})
修改对象属性

在修改响应式对象的属性时,需要通过 action 的方式修改。不通过action修改,mobx会提出警告。虽然直接修改也能生效,但是这样会让 MobX 状态的管理比较混乱,而且将状态修改放到 action 中,能够让 MobX 在内部的事务流程中进行修改,以免拿到的某个属性还处于中间态,最后计算的结果不够准确。

异步操作

在 MobX 中,不管是同步还是异步操作,都可以放到 action 中,只是异步操作在修改属性时,需要将赋值操作放到 runInAction 中。

import { runInAction, makeAutoObservable } from 'mobx'const store = makeAutoObservable({
  count: 0,
  async initCount() {
    // 模拟获取远程的数据
    const count = await new Promise((resolve) => {
      setTimeout(() => {
        resolve(10)
      }, 500)
    })
    // 获取数据后,将赋值操作放到 runInAction 中
    runInAction(() => {
      this.count = count
    })
  }
})
​
store.initCount()

如果不调用 runInAction ,则可以直接调用本身已经存在的 action。

import { runInAction, makeAutoObservable } from 'mobx'const store = makeAutoObservable({
  count: 0,
  setCount(count) {
    this.count = count
  },
  async initCount() {
    // 模拟获取远程的数据
    const count = await new Promise((resolve) => {
      setTimeout(() => {
        resolve(10)
      }, 500)
    })
    // 获取数据后,调用已有的 action
    this.setCount(count)
  }
})
​
store.initCount()

参考内容

juejin.cn/post/692154…

cn.mobx.js.org/