vue中$set原理
Vue 中的 $set
方法(Vue.set
)主要用于 向响应式对象中添加一个新的属性,并确保这个新属性是响应式的,能够触发视图更新。
📌 背景问题:为什么需要 $set
?
在 Vue 2 中,直接给对象新增属性不会触发视图更新,例如:
this.obj.a = 123 // 如果 a 原本不存在,则不会触发视图更新
这是因为 Vue 2 是基于 Object.defineProperty
来实现响应式系统的,它在对象初始化时只能“劫持”已有属性,无法监控新增的属性。
✅ $set
的作用
this.$set(obj, key, value)
或者
Vue.set(obj, key, value)
它的作用是:
-
为对象添加新属性
-
让这个新属性是响应式的
-
触发视图更新
🧠 原理解析(Vue 2)
Vue.set = function (target, key, val) {if (Array.isArray(target) && isValidIndex(key)) {// 对数组使用 splice 替代设置target.splice(key, 1, val)return val}if (key in target && !(key in Object.prototype)) {target[key] = valreturn val}const ob = target.__ob__ // 这是 Observer 实例if (!ob) {target[key] = valreturn val}defineReactive(ob.value, key, val) // 核心:为新属性定义响应式ob.dep.notify() // 通知依赖更新return val
}
核心步骤:
-
判断是否是数组:数组用
splice
替代赋值(因为 Vue 对数组的监听基于方法拦截)。 -
通过
defineReactive()
为新属性添加 getter/setter,注入依赖收集逻辑。 -
通知依赖更新视图(
dep.notify()
)
🧪 示例
<template><div>{{ user.name }}</div><button @click="addProp">添加新属性</button>
</template><script>
export default {data() {return {user: {}}},methods: {addProp() {this.$set(this.user, 'name', '张三') // 触发视图更新}}
}
</script>
🆕 Vue 3 呢?
在 Vue 3 中,由于使用了 Proxy 实现响应式,不需要 $set
了,你可以直接赋值:
reactiveObj.newKey = 123 // ✅ 直接响应式,无需 $set
🧩 总结
项目 | Vue 2 | Vue 3 |
---|---|---|
添加响应式属性 | 需要 $set | 不需要,直接赋值即可 |
实现机制 | Object.defineProperty + defineReactive | Proxy 拦截所有操作 |
数组监听 | 依赖重写 push/splice 等方法 | Proxy 完整拦截 |
需要我帮你用简单代码实现一个简化版的 $set
吗?可以更好理解它的内部逻辑。