Foreword
- By the previous article, we know that the principles of responsive Vue initialization data, and only talked about how the object is
defineReactive
a 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.js
Observer 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 observer
to 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.js
throughout much js file contents, mainly to do a few things
- Create an array prototype, assigned to
arrayMethods
- Array prototype method to rewrite
arrayMethods
and 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.