Vueソースコードの解読はどのように配列の変化を検出します

10605 ワード

前言
前回の記事では、Vue初期化dataの応答式の原理を知っています.オブジェクトがdefineReactive方法でdata属性をモニタリングする方法について説明しただけで、配列は少し持っているだけで、下のソースコードで撫でてみましょう.
まず、この判断src/core/observer/index.js Observerクラス構築関数を参照してください.
//         
 if (Array.isArray(value)) { //    
      if (hasProto) {
        protoAugment(value, arrayMethods) //         
      } else {
        copyAugment(value, arrayMethods, arrayKeys) //         
      }
      this.observeArray(value) //             , observeArray    
    } else { 
      this.walk(value) //               (    )
    }
 }
protoAugment プロトタイプ書き換え方法、プロトタイプ書き換えをarrayMethodsに向ける
/**
 * Augment a target Object or Array by intercepting
 * the prototype chain using __proto__
 */
function protoAugment (target, src: Object) {
  /* eslint-disable no-proto */
  target.__proto__ = src
  /* eslint-enable no-proto */
}
observeArray は主に配列を遍歴し、observerを呼び出してリスニングされたかどうかを判断し、リスニングされていない場合はnew Observer がリスニングを作成し、前述した.
 /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) { //         ,  observer         
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])  //           
    }
  }

配列書き換えプロトタイプと観察者に更新を通知する場所src/core/observer/array.js,jsファイル全体の内容は多くなく,主にいくつかのことをした.
  • 配列プロトタイプを作成し、arrayMethods
  • に割り当てます.
  • 配列プロトタイプメソッドをarrayMethodsに書き換え、this
  • を修正する.
  • 配列変化のデータを観測し,再帰的遍歴法実体を上に見る10行observeArray
  • .
  • wachter更新ビュー
  • に通知する.
    /*
     * 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) //             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) //        this
        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
      })
    })
    
    

    まとめ
    Vueはdata中の配列を関数ハイジャック方式でプロトタイプチェーン書き換えを行った.配列apiを呼び出すと依存更新を通知できるように、独自に定義された配列プロトタイプメソッドを指す.配列に参照タイプが含まれている場合.配列内の参照タイプが再監視されます.