How Vue Vue source of interpretation is to detect changes in the array

Foreword

  • By the previous article, we know that the principles of responsive Vue initialization data, and only talked about how the object is defineReactivea method of data attributes to create the monitor, while the array is just slightly off, below we look through the source code to stroke

First look back to this judgment src/core/observer/index.jsObserver class constructor

// 我们看回这段代码
 if (Array.isArray(value)) { // 是数组
      if (hasProto) {
        protoAugment(value, arrayMethods) // 改写数组原型方法
      } else {
        copyAugment(value, arrayMethods, arrayKeys) // 复制数组已有方法
      }
      this.observeArray(value) // 深度观察数组中的每一项 , observeArray 往下看
    } else { 
      this.walk(value) //是对象则重新定义对象类型数据 (前章讲过)
    }
 }

protoAugment 方法 Rewrite the prototype method, the prototype rewrite point 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 方法Mainly through the array, and then call observerto determine whether've been listening, listening is not being new Observer 类created to listen, I have spoken in front;

 /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) { // 是数组则遍历数组,走进observer方法查看是否被监听
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])  // 观测数组中的每一项 
    }
  }

Array prototype and rewrite local observer notification updates src/core/observer/array.jsthroughout much js file contents, mainly to do a few things

  • Create an array prototype, assigned to arrayMethods
  • Array prototype method to rewrite arrayMethodsand edit this
  • For observing changes in the data array, the recursive traversal method entity look up line 10 observeArray
  • Notice wachter update view
/*
 * 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
  })
})

to sum up

Vue array of data, by way of function hijacking, rewriting conducted prototype chain; an array of points defined by their prototype method, the array such that when invoked api, dependent on the update may be notified if the array contains a reference type;. Will an array of reference types to monitor again.

Published 22 original articles · won praise 44 · views 8236

Guess you like

Origin blog.csdn.net/HiSen_CSDN/article/details/104830369