Vue 给对象添加新属性时视图不更新
vue2.x 的响应式
实现原理:
对象类型:通过
Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)。数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
1
2
3
4Object.defineProperty(data, "count", {
get() {},
set() {},
});
存在问题:
- 新增属性、删除属性, 界面不会更新。
- 直接通过下标修改数组, 界面不会自动更新。
Vue3.0 的响应式
实现原理:
通过 Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
通过 Reflect(反射): 对源对象的属性进行操作。
MDN 文档中描述的 Proxy 与 Reflect:
Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Reflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16new Proxy(data, {
// 拦截读取属性值
get(target, prop) {
return Reflect.get(target, prop);
},
// 拦截设置属性值或添加新属性
set(target, prop, value) {
return Reflect.set(target, prop, value);
},
// 拦截删除属性
deleteProperty(target, prop) {
return Reflect.deleteProperty(target, prop);
},
});
proxy.name = "tom";
解决办法
在 Vue 2 中,当你向一个对象添加新属性时,Vue 不会自动触发视图的更新,因为 Vue 只会追踪已经存在于数据对象中的属性。如果你需要在视图中响应新属性的变化,你可以使用 Vue 的 $set
方法或 JavaScript 的 Object.assign
来更新对象,从而触发视图的刷新。
使用 Vue 的
$set
方法:1
2// 假设你有一个名为 object 的数据对象
this.$set(object, "newProperty", "new value");上面的代码将在
object
对象上添加一个新属性newProperty
,并设置其值为'new value'
,同时会触发视图的更新。**使用 JavaScript 的
Object.assign
**:1
2// 假设你有一个名为 object 的数据对象
object = Object.assign({}, object, { newProperty: "new value" });这将创建一个新对象,包含
object
中的所有属性以及新属性newProperty
,然后将新对象分配给object
,这也会触发视图的更新。$forceUpdate
请注意,
$forceUpdate
应该谨慎使用,因为它会绕过 Vue 的响应式系统,可能会导致性能问题和难以维护的代码。在大多数情况下,应该遵循 Vue 的响应式数据规则,让 Vue 自动处理视图的更新。
无论哪种方法,都可以让 Vue 检测到对象属性的变化并更新视图。确保在操作对象属性之前,你需要确保 Vue 已经响应式地跟踪了该对象,或者使用上述方法来添加新属性。