在 Vue 2 中,this.$set
是一个用于响应式地添加新属性到已有对象的全局 API。它的主要作用是解决 Vue 无法检测到对象属性添加或删除的限制(由于 Vue 2 的响应式系统基于 Object.defineProperty
实现)。
1. 为什么需要 this.$set
?
在 Vue 2 中,直接给对象添加新属性(如 this.obj.newProperty = value
)不会触发视图更新,因为 Vue 无法拦截这种动态添加的属性变化。
2. 语法
this.$set(target, propertyName, value)
target
:目标对象(必须是响应式对象,如 Vue 实例的data
或 Vuex 的state
)。propertyName
:要添加的新属性名(字符串或 Symbol)。value
:新属性的值。
3. 示例
场景 1:动态添加对象属性
// 错误写法(不会触发视图更新)
this.user.age = 25;// 正确写法(使用 $set)
this.$set(this.user, 'age', 25);
场景 2:动态更新数组索引
虽然 Vue 2 对数组的响应式处理有类似限制(无法直接通过索引修改数组,如 this.arr[0] = newValue
),但 $set
也可以用于数组:
// 错误写法
this.items[0] = { name: 'New Item' };// 正确写法
this.$set(this.items, 0, { name: 'New Item' });
4. 替代方案(Vue 3 及 Composition API)
在 Vue 3 中,响应式系统改用 Proxy
,不再需要 $set
,因为动态添加属性会自动被追踪:
// Vue 3 中直接添加即可
this.user.age = 25; // 会自动触发视图更新
5. 注意事项
- 仅对响应式对象有效:如果
target
是非响应式对象(如普通字面量),$set
无效。 - 优先使用 Vue.set:在非组件上下文(如普通函数)中,使用
Vue.set(obj, key, value)
。 - 数组方法:对于数组,优先使用 Vue 重写的响应式方法(如
push
、splice
)。
总结
Vue 版本 | 是否需要 $set | 原因 |
---|---|---|
Vue 2 | ✅ 需要 | 响应式系统基于 defineProperty |
Vue 3 | ❌ 不需要 | 响应式系统基于 Proxy |
在 Vue 2 中,遇到动态添加属性或数组索引更新的场景,记得用 this.$set
!