眾所周知,Vue.js3.0之前是使用了Object.defineProperty來(lái)實(shí)現(xiàn)雙向數(shù)據(jù)綁定。當(dāng)數(shù)據(jù)變化時(shí)瘟芝,會(huì)反應(yīng)到視圖上。但是是有缺陷的褥琐,比如以下情況:
this.arr[1] = 11
this.arr.length = 2
對(duì)數(shù)組的這兩種操作可以改變this.arr锌俱,但是視圖不會(huì)更新。
去搜索敌呈,文章總是一句話(huà)概況:由于js的限制贸宏,Vue無(wú)法檢測(cè)數(shù)組某些變動(dòng)。
暈死磕洪,還是自己動(dòng)手吧?粤贰!析显!
Object.defineProperty
回到原生js鲫咽,我們?cè)囍肙bject.defineProperty來(lái)改寫(xiě)數(shù)據(jù):
var data = {}
Object.defineProperty(data, 'test', {
set (value) {
this.testValue = value
console.log('更新')
},
get () {
return this.testValue
}
})
data.test = [1, 2, 3] // 打印‘更新’
console.log(data.test) // [1, 2, 3]
data.test[3] = 4 // 沒(méi)打印 ‘更新’
console.log(data.test) // [1, 2, 3, 4]
使用array[index]賦值的方式無(wú)法觸發(fā)setter,自然無(wú)法觸發(fā)視圖更新(Vue中,數(shù)據(jù)變動(dòng)分尸,setter調(diào)用notify去更新視圖)锦聊。
Proxy
換一種方式,使用Vue3.0所使用的Proxy代理試試:
var obj = {
test: '',
}
let objProxy = new Proxy(obj, {
get: (target, prop) => {
return prop in target ? target[prop] : '空'
},
set: (target, prop, value) => {
target[prop] = value
console.log('更新')
}
})
objProxy.test = [1, [2, 3], 4] // 打印‘更新’
console.log(obj.test) // [1, [2, 3], 4]
objProxy.test[1][1] = 5 // 沒(méi)打印 ‘更新’
console.log(obj.test) // [1, [2, 5], 4]
結(jié)果顯示箩绍,同樣無(wú)法打印更新孔庭,也就無(wú)法觸發(fā)視圖更新。
好吧伶选,這就是js的限制史飞。
解決
變異方法(Vue中做了變動(dòng),可以觸發(fā)視圖更新):
push()仰税、pop()构资、shift()、unshift()陨簇、splice()吐绵、sort()
對(duì)于修改數(shù)組的某個(gè)元素的值,可以利用Vue提供的方法:
this.$set(data of array, index of array, newValue)
// 例如:
this.$set(this.arr, 1, 4)
還可以使用變異方法中的splice來(lái)替換:
data of array.splice(要插入的位置, 要?jiǎng)h除的項(xiàng)數(shù), 要插入的值)
// 例如:
this.arr.splice(1, 1, 4)
this.array.length = x 也可以使用splice來(lái)操作:
this.arr.splice(2)
這樣河绽,arr就只剩前面兩項(xiàng)己单。
ps:不對(duì)之處,敬請(qǐng)指正0沂巍N屏!