用MobX管理状态(ES5实例描述)-3.常用API

2020-06-15 15:00:18 浏览数 (1)

MobX是一个简单有效的状态管理库,以派生(derive)的概念为核心,以观察者模式为手段,达到了修改数据自动更新界面等目的

  • 正因为其本身提供了包装react的方法,可以简洁的改善react组件,所以官网文档和几乎所有教程都以react和ES7的装饰修饰符等特性为切入点
  • 但MobX在传统的ES5环境中也能良好工作,本文尝试以此为出发点,探讨在既有的非react项目中直接引入MobX并用其整理重构老代码的方法

没有babel、webpack、JSX...那么多的套路!直接上手先,走你~

[III]. 常用API

3.1 computed

computed values指的是从状态或其他派生值中派生出来的值

  • 当依赖的值改变时,派生值也自动更新
  • 产生派生值的函数应该是无副作用的纯函数

除了上面提过的在类实例里使用 getter/setter 和 computed(), computed(expression)也可以直接用来当作一个独立的函数:

代码语言:javascript复制
var name = mobx.observable("John");var upperCaseName = mobx.computed(() =>
   name.get().toUpperCase()
);var disposer = upperCaseName.observe(
   change => console.log(change.newValue)
);name.set("Dave");
// prints: 'DAVE'
处理派生函数中的错误:

应注意正确的报错方式是 throw new Error("err"),而非throw "err"或其他

代码语言:javascript复制
const x = observable(3)
const y = observable(1)
const divided = computed(() => {
   if (y.get() === 0)
       throw new Error("被除数是0")
   return x.get() / y.get()
})divided.get() // returns 3y.set(0) // OK
divided.get() // 报错,此次set失败y.set(2)
divided.get() // 恢复并 Returns 1.5

3.2 autorun

autorun(debugName?, fn) 被用来对那些没有单独设置观察者的状态创建reaction函数

  • 当初始化和依赖的值改变时,相关的函数就会执行
  • autorun的返回值是一个解除观察的函数
代码语言:javascript复制
var str = mobx.observable('are you ok');
str.observe(change=>console.log(change.oldValue, '->', change.newValue));
mobx.autorun(()=>console.log('AAA', str.get()));
str.set('i am fine!');/* 输出:
AAA are you ok
AAA i am fine!
are you ok -> i am fine!
*/
代码语言:javascript复制
var numbers = mobx.observable([1,2,3]);
var sum = mobx.computed(() => numbers.reduce((a, b) => a   b, 0));var disposer = mobx.autorun(() => console.log(sum.get())); // prints '6'numbers.push(4); // prints '10'
disposer();
numbers.push(5); // 无输出
autorun中的错误处理:
代码语言:javascript复制
const age = mobx.observable(10);
const dispose = mobx.autorun(() => {
   if (age.get() < 0)
       throw new Error("年龄不能为负数")
   console.log("Age", age.get())
});mobx.extras.onReactionError(
   (error, derivation)=>console.warn('global err handler: ', error)
);age.set(18);  // Logs: Age 18
age.set(-10); // 报错, 但会在全局err处理中被
age.set(5);   // Recovered, logs Age 5dispose.onError(err=>console.warn(err));age.set(-5);  // 不报错,被onError拦截

3.3 action

  • action(debugName?, fn)语法,创建一个action,用来改变状态
  • action可以用于任何改变可观察状态的方法,或有副作用的方法
  • 对于派生属性对应的setter方法,将自动被视为一个action
  • 设置mobx.useStrict(true),就可以严格限定对状态的改变只能在action中进行
  • action中的fn会被包装上mobx.untracked()mobx.transaction()mobx.extras.allowStateChanges()几个方法,从而使该action达到不被追踪、允许并集中修改状态的目的
  • 如果使用action.bound(fn)替换action(fn),则fn和目标对象绑定,this指向一直都不会变
action中的异步动作:
  • action仅对其包裹的fn生效,而由fn调度的函数则不会有效果
  • 对于一些异步方法,比如setTimeout,promise或async/await,可以将需要异步处理的部分写进runInAction(name?, fn, scope?)
  • runInAction也被用来替换过时的transaction,批量执行多个状态变更,以免触发多次事件
代码语言:javascript复制
var obj = mobx.observable({a:1, b:2});var act = mobx.action(function(){
   setTimeout(function(){
       mobx.runInAction(function(){
           obj.a = 3;
           obj.b = 4;
       });
   }, 1000);
});act();mobx.autorun(function(){
   console.log(obj.a, obj.b);
});/* 输出:
1 2
3 4
*/

* 原创文章转载请注明出处

0 人点赞