initData src\core\instance\state.js

进入到observe src\core\observer\index.js
- 返回一个observe实例
export function observe (value: any, asRootData: ?boolean): Observer | void {
// 观察者
let ob: Observer | void
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if (
shouldObserve &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {// 创建观察者
ob = new Observer(value)
}
if (asRootData && ob) {
ob.vmCount++
}
return ob
}
- Observer对象根据数据类型执行对应的响应化操作
export class Observer {
value: any;
dep: Dep;
constructor (value: any) {
this.value = value
this.dep = new Dep()
def(value, '__ob__', this) // 在getter中可以通过__ob__可获取ob实例
if (Array.isArray(value)) { // 数组响应化
protoAugment(value, arrayMethods)
this.observeArray(value)
} else { // 对象响应化
this.walk(value)
}
}
/**
* 遍历对象所有属性定义其响应化
*/
walk (obj: Object) {
//获取对象所有的key
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
//循环遍历执行defineReactive
defineReactive(obj, keys[i])
}
}
/**
* 对数组每一项执行observe
*/
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
}
- 对象数据响应式 walk(obj:Object)->definReactive(obj,keys[i) definReactive定义对象属性的getter/setter
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
) {
const dep = new Dep() // 一个key一个Dep实例
// 递归执行子对象响应化
let childOb = !shallow && observe(val)
// Object.defineProperty数据拦截,定义当前对象getter/setter
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
// getter负责依赖收集
if (Dep.target) {
//加入到dep去管理watcher
dep.depend()
// 若存在子observer,则依赖也追加到子ob
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value) // 数组需特殊处理
}
}
}
return value
},
set: function reactiveSetter (newVal) {
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
val = newVal // 更新值
//这里递归的目的是,之前的值可能是字符串,赋值可能就是对象,所以childOb更新
childOb = !shallow && observe(newVal)
dep.notify() // 通知更新
}
})
}
我们来看看Dep干了什么 src\core\observer\dep.js
export default class Dep {
static target: ?Watcher; // 依赖收集时的wacher引用
subs: Array<Watcher>; // watcher数组
constructor () {
this.subs = []
}
//添加watcher实例
addSub (sub: Watcher) {
this.subs.push(sub)
}
//删除watcher实例
removeSub (sub: Watcher) {
remove(this.subs, sub)
}
//watcher和dep相互保存引用
depend () {
if (Dep.target) {
Dep.target.addDep(this)
}
}
//通知watcher更新
notify () {
// stabilize the subscriber list first
const subs = this.subs.slice()
for (let i = 0, l = subs.length; i < l; i++) {
subs[i].update()
}
}
}
其实Dep干了什么事呢?就是管理一组Watcher,Dep关联的值更新时通知其管理的Watcher更新。
我们再来看看Watcher干了什么 src\core\observer\watcher.js
export default class Watcher {
constructor (
vm: Component,
expOrFn: string | Function,
cb: Function,
options?: ?Object,
isRenderWatcher?: boolean
) {
this.vm = vm
// 组件保存render watcher,一个组件对应一个渲染watcher
if (isRenderWatcher) {
vm._watcher = this
}
// 组件保存非render watcher (wtach,$watch自动创建的watcher)
vm._watchers.push(this)
// options...
// 将表达式解析为getter函数
// 如果是函数则直接指定为getter,那什么时候是函数?
// 答案是那些和组件实例对应的Watcher创建时会传递组件更新函数updateComponent
if (typeof expOrFn === 'function') {
this.getter = expOrFn
} else {
// 这种是$watch传递进来的表达式,它们需要解析为函数
this.getter = parsePath(expOrFn)
if (!this.getter) {
this.getter = noop
}
}
// 若非延迟watcher,立即调用getter
this.value = this.lazy ? undefined : this.get()
}
/**
* 模拟getter, 重新收集依赖re-collect dependencies.
*/
get () {
// Dep.target = this
pushTarget(this)
let value
const vm = this.vm
try {
// 从组件中获取到value同时触发依赖收集
value = this.getter.call(vm, vm)
}
catch (e) {}
finally {
// deep watching,递归触发深层属性
if (this.deep) {
traverse(value)
}
popTarget()
this.cleanupDeps()
}
return value
}
addDep (dep: Dep) {
const id = dep.id
if (!this.newDepIds.has(id)) {
// watcher保存dep引用
this.newDepIds.add(id)
this.newDeps.push(dep)
// dep添加watcher
if (!this.depIds.has(id)) {
dep.addSub(this)
}
}
}
update () {
// 更新逻辑
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
this.run()
} else {
//默认lazy和sync都是false,所以会走该逻辑,异步更新
queueWatcher(this)
}
}
}
其实Watcher干了什么事呢?监控一个表达式或关联一个组件更新函数,数值更新则指定回调或更新函数(异步更新)被调用。
watcher的数据异步更新queueWatcher怎么实现的。
export function queueWatcher (watcher: Watcher) {
const id = watcher.id
if (has[id] == null) {
has[id] = true
if (!flushing) {
// 入队
queue.push(watcher)
} else {
let i = queue.length - 1
while (i > index && queue[i].id > watcher.id) {
i--
}
queue.splice(i + 1, 0, watcher)
}
// queue the flush
if (!waiting) {
waiting = true
// 执行异步操作
nextTick(flushSchedulerQueue)
}
}
}
nextTick执行异步操作
export function nextTick (cb?: Function, ctx?: Object) {
let _resolve
// callbacks排队做操作
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, 'nextTick')
}
} else if (_resolve) {
_resolve(ctx)
}
})
if (!pending) {
pending = true
// 异步执行策略,兼容性处理
timerFunc()
}
// $flow-disable-line
if (!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
其实数据在做更新时,不会立刻更新,是异步更新。入队操作,入队批量一起执行。
- 数组响应式

// 数组原型
const arrayProto = Array.prototype
// 修改后的原型
export const arrayMethods = Object.create(arrayProto)
// 七个待修改方法
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
/**
* 拦截这些方法,额外发送变更通知
*/
methodsToPatch.forEach(function (method) {
// 原始数组方法
const original = arrayProto[method]
// 修改这些方法的descriptor
def(arrayMethods, method, function mutator (...args) {
// 原始操作
const result = original.apply(this, args)
// 获取ob实例用于通知更新
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)
// 通知更新
ob.dep.notify()
return result
})
})
protoAugment(value,arrayMethods)覆盖数组原型 vue\src\core\observer\index.js
function protoAugment (target, src: Object) {
// 覆盖原来的原型,按照我们拦截后的方法执行的
target.__proto__ = src
}
数组响应式的特殊处理observeArray() vue\src\core\observer\index.js
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
依赖收集时特殊处理 vue\src\core\observer\index.js
//getter中
if (Array.isArray(value)) {
dependArray(value)
}
// 数组中每一项也需要收集依赖
function dependArray (value: Array<any>) {
for (let e, i = 0, l = value.length; i < l; i++) {
e = value[i]
e && e.__ob__ && e.__ob__.dep.depend()
if (Array.isArray(e)) {
dependArray(e)
}
}
}