Mobx
简单、可扩展的状态管理
安装
1 | npm install mobx --save |
observable & autorun
1 | import { observable, autorun } from "mobx"; |
控制台中一次输入 0,1,2
observable 可以用来观测一个数据,这个数据可以是数字、字符串、数组、对象等类型,当观测到的数据发生变化的时候,如果变化的值处在 autorun 中,那么 autorun 就会自动执行。
计算属性–computed
假如现在我们一个数字,但我们对它的值不感兴趣,而只关心这个数组是否为正数。这个时候我们就可以用到 computed 这个属性了。
1 | const number = observable(10); |
依次输出了 true,false,true
依次输出了 true,false,true。
第一个 true 是 number 初始化值的时候,10>0 为 true 没有问题。
第二个 false 将 number 改变为-19,输出 false,也没有问题。
但是当-19 改变为-1 的时候,虽然 number 变了,但是 number 的改变实际上并没有改变 plus 的值,所以没有其它地方收到通知,因此也就并没有输出任何值。
直到 number 重新变为 1 时才输出 true。
action,runInAction 和严格模式(useStrict)
mobx 推荐将修改被观测变量的行为放在 action 中。
1 | import { observable, action } from "mobx"; |
这个类中有一个 add 函数,用来将 number 的值加 1,也就是修改了被观测的变量,根据规范,我们要在这里使用 action 来修饰这个 add 函数。
把@action 去掉,程序还是可以运行
1 | class Store { |
这是因为现在我们使用的 Mobx 的非严格模式,如果在严格模式下,就会报错了。
接下来让我们来启用严格模式
1 | import { observable, action, useStrict } from "mobx"; |
Mobx 里启用严格模式的函数就是 useStrict,注意和原生 JS 的”use strict”不是一个东西。
现在再去掉@action 就会报错了。
action 的写法大概有如下几种:
- action(fn)
- action(name, fn)
- @action classMethod() {}
- @action(name) classMethod () {}
- @action boundClassMethod = (args) => { body }
- @action(name) boundClassMethod = (args) => { body }
- @action.bound classMethod() {}
- @action.bound(function() {})
可以看到,action 在修饰函数的同时,我们还可以给它设置一个 name,这个 name 应该没有什么太大的作用,但可以作为一个注释更好地让其他人理解这个 action 的意图。
action 只能影响正在运行的函数,而无法影响当前函数调用的异步操作
1 | @action createRandomContact() { |
重点关注程序的第六行。在 end 中触发的回调函数,被 action 给包裹了,这就很好验证了上面加粗的那句话,action 无法影响当前函数调用的异步操作,而这个回调毫无疑问是一个异步操作,所以必须再用一个 action 来包裹住它,这样程序才不会报错。。
如果你使用 async function 来处理业务,那么我们可以使用 runInAction 这个 API 来解决之前的问题。
1 | import { observable, action, useStrict, runInAction } from "mobx"; |
runInAction 有点类似 action(fn)()的语法糖,调用后,这个 action 方法会立刻执行。
结合 React 使用
在 React 中,我们一般会把和页面相关的数据放到 state 中,在需要改变这些数据的时候,我们会去用 setState 这个方法来进行改变。
1 | import React from "react"; |
跨组件交互
在不使用其它框架、类库的情况下,React 要实现跨组件交互这一功能相对有些繁琐。通常我们需要在父组件上定义一个 state 和一个修改该 state 的函数。然后把 state 和这个函数分别传到两个子组件里,在逻辑简单,且子组件很少的时候可能还好,但当业务复杂起来后,这么写就非常繁琐,且难以维护。而用 Mobx 就可以很好地解决这个问题。来看看以下的例子:
1 | class MyState { |
网络请求
1 | useStrict(true); |
严格模式下,只能在 action 中修改数据,但是 action 只能影响到函数当前状态下的情景,也就是说在 await 之后发生的事情,这个 action 就修饰不到了,于是我们必须要使用了 runInAction
装饰器报错
下载 npm install @babel/plugin-proposal-decorators
在 package.json 中修改 babel:
1 | "babel": { |
或在 tsconfig.json 中修改:
1 | { |
- Post link: https://blog.gaocaipeng.com/2020/07/02/nhnb6d/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.