vue中檢測數組數據變化方法


  • vue中數組的一些方法是如何進行試圖更新的?
  1. vue中我們對數組進行push,splice,shift的一些操作時候也會觸發render-watcher。這是因為vue中對這些數組的方法進行了一些擴展,使其能夠進行數據的響應式,源碼如下:
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)

// arrayMethods 就是 繼承自 Array.prototype 的數組
// 只需要讓響應式數組 繼承子 arrayMethods

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__ // 是否響應式的標志,保存了依賴收集對象deps
    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
  })
})
  1. 但在vue中對數組的下標賦值處理時,是不會觸發視圖的更新,於是vue提供了一個靜態方法;set、del;數組是通過splice進行操作的,這里列舉一個set源碼:
 export function set (target: Array<any> | Object, key: any, val: any): any {
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val) // 利用擴展的splice方法進行響應式
    return val
  }
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  if (target._isVue || (ob && ob.vmCount)) {
    return val
  }
  if (!ob) {
    target[key] = val
    return val
  }
  defineReactive(ob.value, key, val); // 讓子項響應式
  ob.dep.notify(); // 手動派發更新
  return val
}
  • 簡化原理;
    • 一個數組的原型鏈對應如:arr.proto->Array.prototype-> .proto->Object.prototype;
    • 所以我們可以添加一個__proto__;arr.proto->(Object.create(Array.prototype))->Array.prototype-> .proto->Object.prototype;
    let ARRAY_METHODS = [
        'push',
        'pop',
        'shift',
        'unshift',
        'splice',
        'reverse',
        'sort'
    ];
    let array_methods = Object.create(Array.prototype);
    ARRAY_METHODS.forEach(method=>{
        array_methods[method] = function(){
            console.log('攔截了數組的方法',this);
            let res = Array.prototype[method].apply(this,arguments);
            return res;
        }
    });
    let arr = [];
        arr.__proto__ = array_methods;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM