前言
对象作为JavaScript的一种数据类型,拥有键值对构成的属性。
在Vue的文档中提到,“由于JavaScript的限制,Vue不能检测对象属性的添加或删除”。
所以我探索了一下对象属性变动在Vue中的具体表现。
属性值更新
定义一个对象obj,拥有一个属性count,值为1
设置一个按钮,每次点击对obj.count的值进行+1操作
<template>
<div>
<ul>
<li>count:{{obj.count}}</li>
</ul>
<button @click="plus()">+1</button>
</div>
</template>
<script>
export default {
data () {
return {
obj: {
count: 1
}
}
},
methods: {
plus () {
this.obj.count++
}
}
}
</script>
结果发现,当属性值+1能正常触发DOM元素更新
此时,将obj的count属性值稍加改动,同样设置count为对象,且设置count的属性val,值为1。最后数据如下所示
data () {
return {
obj: {
count: {
val: 1
}
}
}
}
同时模板和方法做对应修改
<ul>
<li>val:{{obj.count.val}}</li>
</ul>
methods: {
plus () {
this.obj.count.val++
}
}
结果,对象中属性的属性同样可以触发DOM元素更新
属性增减
此时,更换按钮操作。
添加一个按钮,点击时,为obj新增一个total属性值
再添加一个按钮,点击时,删除obj的count属性
<template>
<div>
<ul>
<li v-for="(val, key) in obj">{{key}}:{{val}}</li>
</ul>
<button @click="add()">add prop</button>
<button @click="del()">del prop</button>
</div>
</template>
<script>
export default {
data () {
return {
obj: {
count: 1
}
}
},
methods: {
add () {
this.obj['total'] = 2
console.log(this.obj)
},
del () {
delete this.obj['count']
console.log(this.obj)
}
}
}
</script>
结果和官网提示的一样,对象属性的新增与删除不会被检查到,所以DOM元素没有被更新
那么,如果在实际开发中遇到这种情况,我们需要DOM元素被更新怎么办?
解决方法
现提供两种解决方法以供参考。
方法一:Vue文档中提到的,使用Vue.set(vue对象实例中使用vm.$set)为对象新增属性,例如为obj新增total属性,可以修改为
methods: {
add () {
this.$set(this.obj, 'total', 2)
console.log(this.obj)
}
}
使用Vue.set为对象添加的属性为响应式属性,所以可以正常触发DOM元素更新
方法二:比较简单粗暴,别更新什么属性了,直接把整个对象都替换掉。
methods: {
add () {
let temp = Object.assign({}, this.obj)
temp['total'] = 2
this.obj = temp
console.log(this.obj)
}
}
先通过Object.assign克隆一个临时对象,修改临时对象的属性,再将临时对象赋为obj。 此时的obj相当于更新了一个新值,所以触发了DOM元素更新。
方法二还有一个变种方法,实现方式不是通过克隆obj对象,而是先将obj赋一个空对象,再最终修改的对象值。
methods: {
add () {
let temp = this.obj
this.obj = {}
temp['total'] = 2
this.obj = temp
console.log(this.obj)
}
}
方法一和方法二的性能,我没有做过对比,且方法二的变种方法有点耍小聪明的嫌疑,我都写出来仅供大家参考。
看起来对象的属性变化就讲完了,但实际开发中时常会遇到一些更复杂的情况。
后面还会继续补充开发中遇到的例子。