前言
本系列主要整理前端面试中需要掌握的知识点。本节介绍如何动态地给Vue的data添加一个新的属性。
一、场景例子
<body>
<div id="app">
<p v-for="(value,key) in item" :key="key">
{{value}}
</p>
<button @click="addProperty">动态添加新属性</button>
</div>
</body>
</html>
<script>
new Vue({
el:'#app',
data:{
item:{
oldProperty:"旧属性"
}
},
methods: {
addProperty(){
this.item.newProperty = "新属性";
console.log(this.item);
}
},
})
</script>
效果:点击按钮后,输出的结果中有新添加的新属性,但是页面没有显示新属性。
二、原理分析
- vue2使用Object.defineProperty实现数据响应式;
const obj = {}
Object.defineProperty(obj, 'foo', {
get() {
console.log(`get foo:${val}`);
return val
},
set(newVal) {
if (newVal !== val) {
console.log(`set foo:${newVal}`);
val = newVal
}
}
})
}
- 当访问foo属性,或者设置foo值的时候都能触发setter与getter;
- 但是为obj添加新属性的时候,却无法触发事件属性的拦截
bj.bar = '新属性'
原因是一开始obj的foo属性被设成了响应式数据,而bar是后面新增的属性,并没有通过Object.defineProperty设置成响应式数据
三、解决方案
有三种解决方案:
- Vue.set()
- Object.assign()
- $forcecUpdated()
常用的就是Vue.set(),语法为:Vue.set( target, propertyName/index, value )
<script>
new Vue({
el:'#app',
data:{
item:{
oldProperty:"旧属性"
}
},
methods: {
addProperty(){
Vue.set(this.item,"newProperty","新属性")
console.log(this.item);
}
},
})
</script>
|