這是我參與更文挑戰的第7天,活動詳情查看: 更文挑戰html
咱們都知道,Vue2.0對於響應式數據的實現有一些不足:vue
沒法檢測數組/對象的新增?git
Vue檢測數據的變更是經過Object.defineProperty實現的,因此沒法監聽數組的添加操做是能夠理解的,由於是在構造函數中就已經爲全部屬性作了這個檢測綁定操做。github
沒法檢測經過索引改變數組的操做。即vm.items[indexOfItem] = newValue?web
官方文檔中對於這兩點都是簡要的歸納爲「因爲JavaScript的限制」沒法實現,而Object.defineProperty是實現檢測數據改變的方案,那這個限制是指Object.defineProperty嗎?數組
Vue對數組的7個變異方法(push、pop、shift、unshift、splice、sort、reverse)實現了響應式。這裏就不作測試了。咱們測試一下經過索引改變數組的操做,能不能被監聽到。markdown
遍歷數組,用Object.defineProperty對每一項進行監測ide
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function defineGet() {
console.log(`get key: ${key} value: ${value}`)
return value
},
set: function defineSet(newVal) {
console.log(`set key: ${key} value: ${newVal}`)
value = newVal
}
})
}
function observe(data) {
Object.keys(data).forEach(function(key) {
defineReactive(data, key, data[key])
})
}
let arr = [1, 2, 3]
observe(arr)
複製代碼
測試說明函數
經過索引改變arr[1],咱們發現觸發了set,也就是Object.defineProperty是能夠檢測到經過索引改變數組的操做的,那Vue2.0爲何沒有實現呢?是尤大能力不行?這確定毋庸置疑。那他爲何不實現呢?oop
後來我在網上找的時候發現了這個。🌀🔥這是github上,一位開發小哥對尤大提到問題。
小結
:原來是出於對性能緣由的考慮,沒有去實現它。而不是不能實現。
對於對象而言,每一次的數據變動都會對對象的屬性進行一次枚舉,通常對象自己的屬性數量有限,因此對於遍歷枚舉等方式產生的性能損耗能夠忽略不計,可是對於數組而言呢?數組包含的元素量是可能達到成千上萬,假設對於每一次數組元素的更新都觸發了枚舉/遍歷,其帶來的性能損耗將與得到的用戶體驗不成正比,故vue沒法檢測數組的變更。
不過Vue3.0用proxy代替了defineProperty以後就解決了這個問題。
this.$set(array, index, data)
//這是個深度的修改,某些狀況下可能致使你不但願的結果,所以最好仍是慎用
this.dataArr = this.originArr
this.$set(this.dataArr, 0, {data: '修改第一個元素'})
console.log(this.dataArr)
console.log(this.originArr) //一樣的 源數組也會被修改 在某些狀況下會致使你不但願的結果
複製代碼
splice
//由於splice會被監聽有響應式,而splice又能夠作到增刪改。
複製代碼
利用臨時變量進行中轉
let tempArr = [...this.targetArr]
tempArr[0] = {data: 'test'}
this.targetArr = tempArr
複製代碼
this.$set(obj, key ,value) - 可實現增、改
watch時添加deep:true深度監聽
,只能監聽到屬性值的變化,新增、刪除屬性沒法監聽
this.$watch('blog', this.getCatalog, {
deep: true
// immediate: true // 是否第一次觸發
});
複製代碼
watch時直接監聽某個key
watch: {
'obj.name'(curVal, oldVal) {
// TODO
}
}
複製代碼
🔥最後:你們有什麼不一樣的看法,歡迎留言討論。要是以爲不錯,給小攻城獅點個讚唄👀