首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Vue.js技术揭秘-响应式数据对象检测变化的注意事项

检测变化的注意事项

通过前面几节的分析,我们对响应式数据对象以及它的 getter 和 setter 部分做了了解,但是对于一些特殊情况是需要注意的,接下来我们就从源码的角度来看 Vue 是如何处理这些特殊情况的。

对象添加属性

对于使用 实现响应式的对象,当我们去给这个对象添加一个新的属性的时候,是不能够触发它的 setter 的,比如:

但是添加新属性的场景我们在平时开发中会经常遇到,那么 Vue 为了解决这个问题,定义了一个全局 API 方法,它在 中初始化:

这个 方法的定义在 中:

方法接收 3个参数, 可能是数组或者是普通对象, 代表的是数组的下标或者是对象的键值, 代表添加的值。首先判断如果 是数组且 是一个合法的下标,则之前通过 去添加进数组然后返回,这里的 其实已经不仅仅是原生数组的 了,稍后我会详细介绍数组的逻辑。接着又判断 已经存在于 中,则直接赋值返回,因为这样的变化是可以观测到了。接着再获取到 并赋值给 ,之前分析过它是在 的构造函数执行的时候初始化的,表示 的一个实例,如果它不存在,则说明 不是一个响应式的对象,则直接赋值并返回。最后通过 把新添加的属性变成响应式对象,然后再通过 手动的触发依赖通知,还记得我们在给对象添加 getter 的时候有这么一段逻辑:

在 getter 过程中判断了 ,并调用了 收集了依赖,这就是为什么执行 的时候通过 能够通知到 ,从而让添加新的属性到对象也可以检测到变化。这里如果 是个数组,那么就通过 把数组每个元素也去做依赖收集。

数组

接着说一下数组的情况,Vue 也是不能检测到以下变动的数组:

1.当你利用索引直接设置一个项时,例如:

2.当你修改数组的长度时,例如:

对于第一种情况,可以使用:;而对于第二种情况,可以使用 。

我们刚才也分析到,对于 的实现,当 是数组的时候,也是通过 来添加的,那么这里的 到底有什么黑魔法,能让添加的对象变成响应式的呢。

其实之前我们也分析过,在通过 方法去观察对象的时候会实例化 ,在它的构造函数中是专门对数组做了处理,它的定义在 中。

这里我们只需要关注 是 Array 的情况,首先获取 ,这里的 实际上就是判断对象中是否存在 ,如果存在则 指向 , 否则指向 ,来看一下这两个函数的定义:

方法是直接把 原型直接修改为 ,而 方法是遍历 keys,通过 ,也就是 去定义它自身的属性值。对于大部分现代浏览器都会走到 ,那么它实际上就把 的原型指向了 , 的定义在 中:

可以看到, 首先继承了 ,然后对数组中所有能改变数组自身的方法,如 等这些方法进行重写。重写后的方法会先执行它们本身原有的逻辑,并对能增加数组长度的 3 个方法 方法做了判断,获取到插入的值,然后把新添加的值变成一个响应式对象,并且再调用 手动触发依赖通知,这就很好地解释了之前的示例中调用 方法可以检测到变化。

总结

通过这一节的分析,我们对响应式对象又有了更全面的认识,如果在实际工作中遇到了这些特殊情况,我们就可以知道如何把它们也变成响应式的对象。其实对于对象属性的删除也会用同样的问题,Vue 同样提供了 的全局 API,它的实现和 大同小异,甚至还要更简单一些,这里我就不去分析了,感兴趣的同学可以自行去了解。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230122A011FK00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券