【Vue】探索物件屬性變動在Vue中的具體表現

揚神233發表於2018-12-04

前言

物件作為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)
    }
}
複製程式碼

方法一和方法二的效能,我沒有做過對比,且方法二的變種方法有點耍小聰明的嫌疑,我都寫出來僅供大家參考。

看起來物件的屬性變化就講完了,但實際開發中時常會遇到一些更復雜的情況。

後面還會繼續補充開發中遇到的例子。

相關文章