最近工作中遇到了mobx的坑,与Vue2数据劫持一样的坑,没错东家项目中的mobx版本比较旧mobx@4.8
,今天总结一下Mobx老版本及遇到的问题,再探索下mobx中的性能优化。
mobx@4 与用法与我前面一篇文章对mobx的总结用法基本一致,只是有一些细微的区别
runInAction
包裹,没有警告。makeObservable
包裹官方有这么一段话,
mobx<5
的实现 与 Vue2
一样,都是基于Object.defineProperty
+覆盖数组的7个方法。所有Vue2响应式存在的问题 ,在mobx中同样存在。
当然也有解决方式 就是对变量 直接赋值新对象,代价是会有重复的渲染(一些组件引用了obj的属性,但值没有变化,也会渲染)。
jsimport { action, observable} from 'mobx';
class AppState {
@observable list = [];
@action push = () => {
this.list.push({id: Math.random()});
}
}
export default window.bb = new AppState()
如果我们对list
进行操作,修改length
,对数组元素进行赋值list[x]=xxx
都没呕问题。但是不能修改数组元素属性list[x].name='xx'
(失去了响应式)
然而这些问题在mobx>=5
的版本中都没有问题
proxy 数据劫持,除了解决了上述问题,还有更好的性能提升
Object.defineProperty
本质是对对象进行遍历,收集依赖进行递归便利不仅耗时,也产生了大量闭包造成内存占用,Proxy
是惰性执行,按需对数据劫持,有更好的性能然而Proxy也并非完美,代理对象与原对象是不同的对象,对代理对象进行解构,会得到原始对象,对原始对象的操作没有响应性。
对于react项目 mobx从4升到5,react也要配套升级
此外由于Proxy独特特性 babel不提供补丁,也就好说android>=7
、ios>=10
的手机才能运行
前面提到 通过Object.assign
或deepMerge
的方式可以减少不必要的渲染,但是要注意前面的坑,也就是说必须事先声明好对象的完整keys。
本文作者:郭郭同学
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!