如何临时阻止MobX触发observers,实现属性临时修改回滚不触发更新
MobX临时修改observable不触发观察者的可行方案
原因说明
你遇到的runInAction包裹后依然触发观察者的问题,本质是两个常见原因:
- 如果你使用的是
autorun/reaction这类高层响应式API:MobX默认对值做浅比较,若你修改的是引用类型,临时修改后回滚的对象和原对象值相等但引用不同,MobX会判定为值发生变更触发通知; - 如果你使用的是
observe这类低级别监听API:它默认每次修改都会同步触发回调,不受runInAction的批量更新逻辑限制,哪怕最终值和初始值一致也会触发两次修改通知。
可行方案
方案1:优先使用拷贝修改(最安全无副作用)
直接深拷贝当前observable的值,修改拷贝后用于数据分析,全程不触碰原observable对象,从根源上避免触发任何监听。
import { toJS } from 'mobx' // 导出原始值的普通JS拷贝 const tempData = toJS(targetObservable) // 修改拷贝做分析,原observable完全不受影响 tempData.targetProp = '临时值' analyze(tempData)
方案2:绕过MobX代理直接修改原始对象
如果你必须修改原observable对象,可以用MobX提供的raw API直接操作底层原始对象,修改行为不会被MobX的监听捕获:
import { getRaw } from 'mobx' // 取原始未被代理的对象 const rawObj = getRaw(targetObservable) const originalVal = rawObj.targetProp // 直接修改原始对象,不触发监听 rawObj.targetProp = '临时值' analyze(targetObservable) // 回滚原值 rawObj.targetProp = originalVal
方案3:临时全局禁用观测通知
如果需要批量修改多个observable且全程不触发通知,可以临时修改MobX全局配置,操作完成后务必改回原配置:
import { configure, runInAction } from 'mobx' // 保存原配置 const originalConfig = configure({ disableObserving: true }) // 执行修改+分析+回滚逻辑 runInAction(() => { const originalVal = targetObservable.targetProp targetObservable.targetProp = '临时值' analyze(targetObservable) targetObservable.targetProp = originalVal }) // 恢复原配置 configure(originalConfig)
方案4:适配runInAction的浅比较逻辑
如果要继续用runInAction的批量更新能力,只需要保证回滚后的值和初始值浅比较相等即可:
- 基础类型值:直接回滚原值即可,MobX 6+会自动对比最终值,一致就不会触发高层响应式API
- 引用类型值:不要创建新对象赋值,直接修改原引用的属性最后还原,或者回滚时赋值原来的引用对象,不要用值相同的新对象
内容的提问来源于stack exchange,提问作者Jos Warmer
相关产品推荐
相关产品推荐

