龙空技术网

浅析数组变化的监听问题

尚学堂IT精英 73

前言:

现时各位老铁们对“js数组对比更新对象变动的值”大概比较着重,朋友们都想要剖析一些“js数组对比更新对象变动的值”的相关知识。那么小编同时在网络上搜集了一些对于“js数组对比更新对象变动的值””的相关资讯,希望姐妹们能喜欢,咱们快快来学习一下吧!

如何监听数组变化?在 Vue 的数据绑定中会对一个对象属性的变化进行监听,并且通过依赖收集做出相应的视图更新等等。那么一个对象所有类型的属性变化都能被监听到吗?之前用 Object.defineProperty通过对象的 getter/setter简单的实现了对象属性变化的监听,并且去通过依赖关系去做相应的依赖处理。但是,这是存在问题的,尤其是当对象中某个属性的值是数组的时候。

由于 JavaScript 的限制,Vue 无法检测到以下数组变动:当你使用索引直接设置一项时,例如 vm.items[indexOfItem] = newValue,当你修改数组长度时,例如 vm.items.length = newLength。从 Vue 源码中也可以看到确实是对数组做了特殊处理的。原因就是 ES5 及以下的版本无法做到对数组的完美继承。

从结果可以看出问题所在,data中 name、userInfo、list 属性的值均发生了变化,但是数组 list 的变化并没有被 observe监听到。原因是什么呢?尚学堂·百战程序员陈老师指出,操作数组的方法,也就是 Array.prototype上挂载的方法并不能触发该属性的 setter,因为这个属性并没有做赋值操作。

如何解决这个问题?

Vue 中解决这个问题的方法,是将数组的常用方法进行重写,通过包装之后的数组方法就能够去在调用的时候被监听到。在这里,我想的一种方法与它类似,大概就是通过原型链去拦截对数组的操作,从而实现对操作数组这个行为的监听。

Proxy顾名思义,就是代理的意思,这是一个能让我们随意玩弄对象的特性。当我们,通过Proxy去对一个对象进行代理之后,我们将得到一个和被代理对象几乎完全一样的对象,并且可以对这个对象进行完全的监控。

什么叫完全监控?Proxy所带来的,是对底层操作的拦截。前面我们在实现对对象监听时使用了Object.defineProperty,这个其实是 JS 提供给我们的高级操作,也就是通过底层封装之后暴露出来的方法。Proxy的强大之处在于,我们可以直接拦截对代理对象的底层操作。这样我们相当于从一个对象的底层操作开始实现对它的监听。

对于一个对象中的基础类型的属性,我们还是通过Object.defineProperty来实现响应式的属性,因为这里并不存在痛点,但是在实现对Object类型的属性进行监听的时候,我采用的是创建代理,因为我们之前的痛点在于无法去有效监听数组的变化。当我们使用这种改进方法之后,我们不用像之前通过重写数组的方法来实现对数组操作的监听了,因为之前这种方法存在很多的局限性,我们不能覆盖所有的数组操作,同时,我们也不能响应到类似于data.array.length = 0这种操作。通过代理实现之后,一切都不一样了。我们可以从底层就实现对数组的变化进行监听。甚至能watch到数组长度的变化等等各种更加细节的东西。这无疑解决了很大的问题。

标签: #js数组对比更新对象变动的值 #js数组对比更新对象变动的值怎么算