返回

揭开Vue神奇的$set方法背后的奥秘

前端

在日常的Vue开发中,我们经常会遇到这样的场景:直接修改数组下标来更改数组中的元素,或者给对象添加新的属性,然而,这种直接修改的方式并不会触发Vue的响应式系统,导致数据更新无法被侦测到,影响界面的正常更新。

为了解决这个问题,Vue提供了一个神奇的方法——$set。它允许我们在修改数组或对象时,同时触发响应式系统,确保数据更新能够被正确地侦测到,从而实现界面的动态更新。

如何使用$set方法?

$set方法的使用非常简单,其语法如下:

Vue.set(target, key, value)

其中,target表示要修改的目标数组或对象,key表示要修改的属性名或数组下标,value表示要赋予的新值。

例如,假设我们有一个Vue组件,其数据对象中有一个名为“items”的数组,我们想要动态地向这个数组中添加一个新元素,可以使用如下代码:

this.$set(this.items, 3, 'New Item')

在执行这段代码后,“items”数组的第三个元素将被设置为“New Item”,并且Vue的响应式系统将会侦测到这个变化,从而触发界面的更新。

$set方法的实现原理

那么,$set方法是如何实现的呢?我们一起来看看它的源代码:

Vue.set = function (target, key, value) {
  if (Array.isArray(target)) {
    // 修改数组
    target.length = Math.max(target.length, key)
    target[key] = value
    return
  }

  if (hasOwn(target, key)) {
    // 修改对象
    target[key] = value
    return
  }

  const ob = target.__ob__
  if (ob && ob.key) {
    // 修改响应式对象
    set(target, ob.key, value)
    return
  }

  if (target._isVue || (target instanceof Vue)) {
    // 修改Vue实例
    set(target, key, value)
    return
  }

  target[key] = value
}

从源代码中可以看出,$set方法的实现原理主要分为以下几种情况:

  • 修改数组: 如果目标是一个数组,$set方法会将数组的长度设置为key的最大值,然后将value赋给数组的相应位置。
  • 修改对象: 如果目标是一个对象,并且该对象拥有一个名为“ob”的属性,则表明该对象是一个响应式对象。$set方法会使用set方法将value赋给该对象的相应属性。
  • 修改Vue实例: 如果目标是一个Vue实例,$set方法会使用set方法将value赋给该Vue实例的相应属性。
  • 其他情况: 如果目标不是数组、对象或Vue实例,$set方法会直接将value赋给目标的相应属性。

需要注意的是,在使用$set方法时,如果目标是一个响应式对象,则必须使用set方法来修改其属性值,否则不会触发Vue的响应式系统。