1. 程式人生 > 實用技巧 >為什麼Vue中陣列變異方法觸發檢視更新【Vue從原始碼找答案(二)】

為什麼Vue中陣列變異方法觸發檢視更新【Vue從原始碼找答案(二)】

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 排版