一. 问题:vue开发中动态给data添加一个新的属性会遇到数据更新,但是页面没有更新的情况。
例如这段代码:
<p v-for="(value,key) in item" :key="key">
{{ value }}
</p>
<button @click="addProperty">动态添加新属性</button>
const app = new Vue({
el:"#app",
data:()=>{
item:{
oldProperty:"旧属性"
}
},
methods:{
addProperty(){
this.items.newProperty = "新属性" // 为items添加新属性
console.log(this.items) // 输出带有newProperty的items
}
}
})
点击按钮,发现数据虽然更新了(console
打印出了新属性),但页面并没有更新
二. 原因
由于vue2
是用Object.defineProperty
实现数据响应式
const obj = {}
Object.defineProperty(obj, 'a', {
get() {
console.log(`get a:${val}`);
return val
},
set(newVal) {
if (newVal !== val) {
console.log(`set a:${newVal}`);
val = newVal
}
}
})
}
当我们设置a
值的时候都能够触发setter
与getter,
但是我们为obj
添加新属性的时候,却无法触发。
原因是一开始obj
的a
属性被设成了响应式数据,而后面新增的属性,并没有通过Object.defineProperty
设置成响应式数据
三. 解决方案
1. Vue.set()
通过Vue.set
向响应式对象中添加一个property
,并确保这个新 property
同样是响应式的,且触发视图更新
2. Object.assign()
创建一个新的对象, 使用Object.assign()
合并原对象和混入对象的属性
3. $forcecUpdated()
$forceUpdate
强制更新,可以让Vue
实例重新渲染