当前位置:首页 > VUE

vue.set实现原理

2026-02-22 18:30:15VUE

Vue.set 的实现原理

Vue.set 是 Vue.js 提供的一个全局 API,用于向响应式对象添加新属性并确保新属性也是响应式的。其核心原理基于 Vue 的响应式系统。

响应式系统的核心机制

Vue 的响应式系统通过 Object.defineProperty 或 Proxy(Vue 3)实现数据劫持。当对象被初始化为响应式时,Vue 会递归地遍历对象的所有属性,将它们转换为 getter/setter。但对于后续动态添加的属性,Vue 无法自动检测到变化。

Vue.set 的作用

Vue.set 解决了动态添加属性的响应式问题。它通过以下方式工作:

  • 对于目标对象是数组的情况,使用数组的 splice 方法触发响应式更新。
  • 对于目标对象是普通对象的情况,通过 defineReactive 方法将新属性转换为响应式属性。
  • 触发依赖通知,通知所有订阅者(Watcher)进行更新。

源码解析

以下是 Vue 2.x 中 Vue.set 的核心实现逻辑(简化版):

function set(target, key, value) {
  // 处理数组情况
  if (Array.isArray(target)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, value)
    return value
  }

  // 处理已存在属性
  if (key in target && !(key in Object.prototype)) {
    target[key] = value
    return value
  }

  // 处理新增属性
  const ob = target.__ob__
  if (!ob) {
    target[key] = value
    return value
  }

  // 将新属性转为响应式
  defineReactive(ob.value, key, value)
  // 通知依赖更新
  ob.dep.notify()
  return value
}

使用场景

Vue.set 主要在以下场景中使用:

  • 动态添加对象属性时
  • 通过索引修改数组元素时(替代直接索引赋值)
  • 添加数组新元素时(超出当前数组长度)

与直接赋值的区别

直接给对象添加新属性不会触发视图更新,因为新属性没有被转换为响应式属性。Vue.set 能够确保新属性被正确劫持并触发视图更新。

Vue 3 的变化

在 Vue 3 中,由于使用 Proxy 实现响应式,Vue.set 不再是必须的,因为 Proxy 可以拦截所有属性访问和修改操作,包括动态添加的属性。但为了兼容性,Vue 3 仍然保留了类似功能的 API。

vue.set实现原理

标签: 原理vue
分享给朋友:

相关文章

vue实现下拉刷新组件

vue实现下拉刷新组件

实现下拉刷新组件的核心思路 下拉刷新功能通常通过监听触摸事件、滚动位置和动画效果实现。Vue中可以利用自定义指令或封装组件完成,以下为两种常见实现方式。 基于自定义指令的实现 创建指令监听触摸事件…

vue 实现grid

vue 实现grid

在Vue中实现Grid布局可以通过多种方式完成,以下是几种常见的方法: 使用CSS Grid布局 CSS Grid是一种强大的布局系统,可以直接在Vue组件的样式中使用。以下是一个简单的示例:…

vue实现tag

vue实现tag

Vue 实现标签(Tag)功能 在 Vue 中实现标签(Tag)功能可以通过多种方式完成,以下是一些常见的方法和实现步骤: 使用动态组件和 v-for 通过 v-for 指令动态渲染标签列表,结合样…

vue实现公式

vue实现公式

在Vue中实现公式展示或计算可以通过多种方式实现,以下为具体方法: 使用模板插值与计算属性 若公式较简单,可直接在模板中使用插值表达式或计算属性。例如计算圆的面积: <templat…

vue compile 实现

vue compile 实现

Vue 编译实现原理 Vue 的编译过程将模板字符串转换为渲染函数,主要分为解析、优化和代码生成三个阶段。 解析阶段(Parse) 将模板字符串转换为抽象语法树(AST)。Vue 使用正则表达式和…

vue实现骰子

vue实现骰子

Vue 实现骰子功能 创建 Vue 组件 在 Vue 项目中创建一个骰子组件,例如 Dice.vue。该组件包含骰子的外观和逻辑。 <template> <div class…