lulujianglab / blog

:bento:lulujiang blog
https://lulujianglab.com/
83 stars 4 forks source link

mobx 快速剖析 #51

Open lulujianglab opened 4 years ago

lulujianglab commented 4 years ago

由于近期 react 项目的数据状态是用 mobx 来管理,所以为了尽快上手项目,花了点时间研究了下,效果显著,所以特意总结了以下内容,可以用来快速理解 mobx 和上手项目

mobx 介绍

首先我们还是来快速介绍下 mobx 以及为什么需要 mobx

mobx 是什么

mobx 是一个前端领域的 js 框架,官方定义为简单、可扩展的状态管理

我们知道对于项目应用来说,数据是必不可少的,数据变量会记录某个时刻的状态,从而影响应用下一个时刻的状态 特别是对于高度封装的组件化模块而言,需要内部状态变量维持组件自身的独立运行 当应用复杂度上升之后,状态变量的数量急剧增多,并且它们之间能相互变化影响 自然的状态管理就比较困难了,容易造成状态的变化不受控制 这个时候引入状态管理工具来管理应用的众多状态数据就显得格外的重要

mobx 就是这样一个来管理状态数据的工具

mobx 与 redux 的关系

它两同样都是管理应用程序的状态

综合来说,mobx 能提供比 redux 学习成本更低、对性能优化更友好的解决方案

对于既使用过 redux 又正在使用 mobx 的我来说,mobx 确实在代码量和第三方库以及维护成本上来说,要比 redux 更低点,但也正因为这样它的封装度更高,不利于接触底层的逻辑

mobx 的核心思想

概括来说,mobx 有几下几处核心点

image

image

简单来说,就是 Action => State => Reaction,用 Action 函数来操作 State,State 的变化自动到 Reaction 副作用

基础语法

学习 mobx 需要我们提前掌握 ES6 的两个语法知识

mobx 常用 API

可观察的数据(observable)

observable 是一种让数据的变化可以被观察的方法 同时,observable 上还挂载了另一个方法 box: observable.box

对于原型类型:String Number Boolean Symbol,以及对象和数组这些数据类型都是可被观察的

mobx 对任意变量的处理方式有两种

// get方法用于返回原始类型值 set方法修改原始类型值 num.set(50) console.log(num.get())


## store 中的写法 - decorator

```js
class Store {
  @observable array = []
  @observable obj = {}
  @observable map = new Map()

  @observable string = 'hello'
  @observable number = 20
  @observable bool = false

  // computed 作为 decorator 来修饰类的 get 成员
  @computed get mixed() {
    return store.string + '/' + store.number
  }

  @action bar() {
    this.string = 'world'
    this.number = 30
  }
  // @action.bound bar() {
  //   this.string = 'world'
  //   this.number = 30
  // }
}

此时会识别 observable 是普通函数还是 decorator,如果是 decorator,则会自动判断是普通数据类型还是复杂类型,自动调用box方法

对可观察的数据做出反应

总结来说

修改可观察数据( action )

频繁的数据变动会触发副作用,性能会有一定损失。为了提升频繁触发副作用造成的性能问题,mobx 引入了 action 的概念 action 被定义为任何修改状态的行为,核心是将多次对状态数据的赋值合并成一次

与 observable、computed 类似,action 也是可作为普通函数和 decorator 使用,最常用也是推荐的方式是 decorator

store.bar() // 只会执行一次

action.bound 与action类似,会将被修饰的方法的上下文强制绑定到该对象上

var bar = store.bar
bar() // 放在当前的上下文执行

语法糖:runInAction,随时定义匿名的 action 方法可以运行它

runInAction(() => {
  store.string = 'world'
  store.number = 30
})

对于有多处重复调用的处理逻辑,可用 action 来实现复用,否则,用 runInAction 即可 runInAction 也可接收多一个字符串类型的参数,有利于调试

runInAction('modify', () => {
  store.string = 'world'
  store.number = 30
})

mobx应用

使用mobx-react

mobx-react 的 observer 方法可以将 react 的 render 方法包装成 autorun observer 修饰器是修饰类本身的(组件类),不是类成员

mobx 精确知道 autorun 依赖哪些数据,做到按需触发 所以是谁真正用到被观察数据,谁就重渲染,也就需要被 observer 修饰 一般建议将所有 react 组件都被 observer 修饰,没有副作用,避免组件过多产生不渲染的问题

同时,需要将react中的用户操作行为转换为action,将数据绑定到react组件上,以驱动视图

需要注意的是:

可变数据用 @observable 修饰;get 属性或者是依赖可归纳数据的属性,建议使用 computed 修饰;mobx 上有 remove 方法,可以方便实现删除操作

常用工具函数

提升性能

尽管 mobx 在提升性能上要好与 redux,但我们在平常项目开发中仍要注意几点

实例

基于以上总结,我实现了个 TodoList,包含基本的增删改查功能和性能优化