vm.$set的原理

本文详细探讨了Vue.js中vm.$set的用法和实现原理。针对Array和Object两种情况,分析了如何确保新增属性成为响应式的,并通过setter触发视图更新。对于Array,vm.$set利用splice方法确保元素被正确添加并保持响应性;对于Object,当属性不存在时,通过defineReactive将其转换为响应式属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在vue.js中,vm.$set是一个比较常用的API,先简单回顾一下用法。
在这里插入图片描述

一.用法:

vm.$set(target, key, value)
参数
{object | Array} target
{string | number} key
{any} value
返回值:{function} unwatch
用法:在object上设置一个属性,如果object是响应式的,vue.js会保证属性被创建后也是响应式的,并且触发视图更新。这个方法主要是用来避开vue.js不能侦测属性被添加的限制。
注意:target不能是vue.js实例或者vue.js实例的根数据对象。
了解了变化侦测原理,我们知道了只有已经存在的属性的变化才会被追踪到,新增的属性无法被追踪到。因为在ES6之前,javascript并没有提供元编程的能力,所以根本无法侦测object什么时候被添加了一个新的属性。而vm.$set就是为了解决这个问题而出现的,使用它可以为Object新增属性,然后vue.js就可以将这个新增属性转换成响应式的。
问题是怎样出现的呢?举个例子:
在这里插入图片描述
data中有一个obj对象,如果直接给obj设置一个属性,例如:
在这里插入图片描述
在action方法被调用时,会为obj新增一个name属性,而vue.js不会得到任何通知,新增的这个属性也不是响应式的,vue.js根本不知道这个obj新增了属性,就好像vue.js无法知道我们使用了array.length=0清空了数组一样。
vm.$set就可以解决这个事情,我们来看看vm.$set是如何实现的:

  import {set} from '../observer/index'
  Vue.prototype.$set = set;

这里我们在vue.js的原型上设置了$set属性,其实所有以vm.$开头的方法都是在vue.js的原型上设置的,vm.$set的具体实现其实是在observer中抛出的set方法。所以我们先创建一个set方法。
export function set(target, key, val){}

二.set方法对于target是Array的处理

在这里插入图片描述
在上面的代码中:

  • ①如果target是数组并且key是一个有效的索引值,就先设置length属性。②如果传递的索引值key大于当前数组的lenght,就让target的length等于索引值。
  • 通过splice方法把val设置到target中的指定位置(参数中提供的索引值的位置)
  • 当我们使用splice方法把val设置到target中的时候,数组拦截器会侦测到target发生了变化,并且会自动帮助我们把这个新增的val转换成响应式的。
  • 最后返回val即可

三.set方法对于target是Object的处理

如果target是obejct,则对于key分为俩种情况:
①key已经存在于target中
②key不存在target中,而是新增的属性。
1.key已经存在于target中
在这里插入图片描述
因为key已经存在于target中,所以其实这个key已经被侦测了变化。也就是说,这种情况属于修改数据,直接用key和val改数据就好了。修改数据的动作会被vue.js侦测到,所以数据发送变化后,会自动向依赖发送通知。
2.key不存在target中,而是新增的属性
在这里插入图片描述
在这里插入图片描述

  • 在上面的代码中,最先获得target的__ob__属性;
  • 判断target是否是vue.js实例或vue.js实例的根数据对象。使用target._isVue来判断是不是vue.js实例。使用ob.vmCount来判断它是不是根数据对象。什么是根数据呢?this.$data就是根数据。
  • 接下来处理target不是响应式的情况。如果target身上没有__ob__属性,说明它并不是响应式的,不需要做什么特殊处理,只需要通过key和val在target上设置。
  • 如果上面条件都不满足,那么说明用户是在响应式数据上新增了一个属性,这种情况下需要追踪这个新属性的变化,即使用defineReactive将新增属性转换为getter/setter的形式即可。
  • 最后向target的依赖触发变化的通知,并返回val.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值