為什麼Vue中陣列變異方法觸發檢視更新【Vue從原始碼找答案(二)】
阿新 • • 發佈:2020-08-01
Vue中陣列變異方法觸發檢視更新
❝以下介紹來自Vue文件中的 深入響應式原理
❞
由於 JavaScript 的限制,Vue 不能檢測陣列的變化
Vue 不能檢測以下陣列的變動:
當你利用索引直接設定一個數組項時,例如:vm.items[indexOfItem] = newValue
當你修改陣列的長度時,例如:vm.items.length = newLength
舉個例子:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是響應性的
vm.items.length = 2 // 不是響應性的
為了解決第一類問題,以下兩種方式都可以實現和 vm.items[indexOfItem] = newValue
相同的效果,同時也將在響應式系統內觸發狀態更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set 例項方法,該方法是全域性方法 Vue.set 的一個別名:
vm.$set(vm.items, indexOfItem, newValue)
為了解決第二類問題,你可以使用 splice:
vm.items.splice(newLength)
❝以上介紹來自Vue文件中的 深入響應式原理
❞
為什麼這些陣列變異方法可以觸發狀態更新?
push() pop() shift() unshift() splice() sort() reverse()
Vue 將被偵聽的陣列的變更方法進行了包裹,所以它們也將會觸發檢視更新
以下是 Vue 中
/*
* not type checking this file because flow doesn't play well with
* dynamically accessing methods on Array prototype
*/
import { def } from '../util/index'
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
/**
* Intercept mutating methods and emit events
*/
methodsToPatch.forEach(function (method) {
// cache original method
const original = arrayProto[method]
// 重新定義變異方法
def(arrayMethods, method, function mutator (...args) {
// 執行原方法
const result = original.apply(this, args)
const ob = this.__ob__
let inserted //新插入的物件
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted) // 觀察新插入物件
// notify change
ob.dep.notify() // 通知更新
return result
})
})
本文使用 mdnice 排版