前言
物件作為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)
}
}
複製程式碼
方法一和方法二的效能,我沒有做過對比,且方法二的變種方法有點耍小聰明的嫌疑,我都寫出來僅供大家參考。
看起來物件的屬性變化就講完了,但實際開發中時常會遇到一些更復雜的情況。
後面還會繼續補充開發中遇到的例子。