function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) }
/** * Attempt to create an observer instance for a value, * returns the new observer if successfully observed, * or the existing observer if the value already has one. */ /* 尝试创建一个Observer实例(__ob__),如果成功创建Observer实例则返回新的Observer实例,如果已有Observer实例则返回现有的Observer实例。 */ export function observe (value: any, asRootData: ?boolean): Observer | void { /*判断是否是一个对象*/ if (!isObject(value)) { return } let ob: Observer | void
/*这里用__ob__这个属性来判断是否已经有Observer实例,如果没有Observer实例则会新建一个Observer实例并赋值给__ob__这个属性,如果已有Observer实例则直接返回该Observer实例*/ if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__ } else if (
/*这里的判断是为了确保value是单纯的对象,而不是函数或者是Regexp等情况。*/ observerState.shouldConvert && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { ob = new Observer(value) } if (asRootData && ob) {
/*如果是根数据则计数,后面Observer中的observe的asRootData非true*/ ob.vmCount++ } return ob }
/** * Observer class that are attached to each observed * object. Once attached, the observer converts target * object's property keys into getter/setters that * collect dependencies and dispatches updates. */ export class { value: any; dep: Dep; vmCount: number; // number of vms that has this object as root $data
constructor (value: any) { this.value = value this.dep = new Dep() this.vmCount = 0
/* 将Observer实例绑定到data的__ob__属性上面去,之前说过observe的时候会先检测是否已经有__ob__对象存放Observer实例了,def方法定义可以参考https://github.com/vuejs/vue/blob/dev/src/core/util/lang.js#L16 */ def(value, '__ob__', this) if (Array.isArray(value)) {
/** * Walk through each property and convert them into * getter/setters. This method should only be called when * value type is Object. */ walk (obj: Object) { const keys = Object.keys(obj)
/*walk方法会遍历对象的每一个属性进行defineReactive绑定*/ for (let i = 0; i < keys.length; i++) { defineReactive(obj, keys[i], obj[keys[i]]) } }
/** * Observe a list of Array items. */ observeArray (items: Array<any>) {
/*数组需要便利每一个成员进行observe*/ for (let i = 0, l = items.length; i < l; i++) { observe(items[i]) } } }
constructor ( vm: Component, expOrFn: string | Function, cb: Function, options?: Object ) { this.vm = vm /*_watchers存放订阅者实例*/ vm._watchers.push(this) // options if (options) { this.deep = !!options.deep this.user = !!options.user this.lazy = !!options.lazy this.sync = !!options.sync } else { this.deep = this.user = this.lazy = this.sync = false } this.cb = cb this.id = ++uid // uid for batching this.active = true this.dirty = this.lazy // for lazy watchers this.deps = [] this.newDeps = [] this.depIds = new Set() this.newDepIds = new Set() this.expression = process.env.NODE_ENV !== 'production' ? expOrFn.toString() : '' // parse expression for getter /*把表达式expOrFn解析成getter*/ if (typeof expOrFn === 'function') { this.getter = expOrFn } else { this.getter = parsePath(expOrFn) if (!this.getter) { this.getter = function () {} process.env.NODE_ENV !== 'production' && warn( `Failed watching path: "${expOrFn}" ` + 'Watcher only accepts simple dot-delimited paths. ' + 'For full control, use a function instead.', vm ) } } this.value = this.lazy ? undefined : this.get() }
/** * Evaluate the getter, and re-collect dependencies. */ /*获得getter的值并且重新进行依赖收集*/ get () { /*将自身watcher观察者实例设置给Dep.target,用以依赖收集。*/ pushTarget(this) let value const vm = this.vm
/* 执行了getter操作,看似执行了渲染操作,其实是执行了依赖收集。 在将Dep.target设置为自生观察者实例以后,执行getter操作。 譬如说现在的的data中可能有a、b、c三个数据,getter渲染需要依赖a跟c, 那么在执行getter的时候就会触发a跟c两个数据的getter函数, 在getter函数中即可判断Dep.target是否存在然后完成依赖收集, 将该观察者对象放入闭包中的Dep的subs中去。 */ if (this.user) { try { value = this.getter.call(vm, vm) } catch (e) { handleError(e, vm, `getter for watcher "${this.expression}"`) } } else { value = this.getter.call(vm, vm) } // "touch" every property so they are all tracked as // dependencies for deep watching /*如果存在deep,则触发每个深层对象的依赖,追踪其变化*/ if (this.deep) { /*递归每一个对象或者数组,触发它们的getter,使得对象或数组的每一个成员都被依赖收集,形成一个“深(deep)”依赖关系*/ traverse(value) }
/*将观察者实例从target栈中取出并设置给Dep.target*/ popTarget() this.cleanupDeps() return value }
/** * Add a dependency to this directive. */ /*添加一个依赖关系到Deps集合中*/ addDep (dep: Dep) { const id = dep.id if (!this.newDepIds.has(id)) { this.newDepIds.add(id) this.newDeps.push(dep) if (!this.depIds.has(id)) { dep.addSub(this) } } }
/** * Clean up for dependency collection. */ /*清理依赖收集*/ cleanupDeps () { /*移除所有观察者对象*/ let i = this.deps.length while (i--) { const dep = this.deps[i] if (!this.newDepIds.has(dep.id)) { dep.removeSub(this) } } let tmp = this.depIds this.depIds = this.newDepIds this.newDepIds = tmp this.newDepIds.clear() tmp = this.deps this.deps = this.newDeps this.newDeps = tmp this.newDeps.length = 0 }
/** * Subscriber interface. * Will be called when a dependency changes. */ /* 调度者接口,当依赖发生改变的时候进行回调。 */ update () { /* istanbul ignore else */ if (this.lazy) { this.dirty = true } else if (this.sync) { /*同步则执行run直接渲染视图*/ this.run() } else { /*异步推送到观察者队列中,由调度者调用。*/ queueWatcher(this) } }
/** * Scheduler job interface. * Will be called by the scheduler. */ /* 调度者工作接口,将被调度者回调。 */ run () { if (this.active) { const value = this.get() if ( value !== this.value || // Deep watchers and watchers on Object/Arrays should fire even // when the value is the same, because the value may // have mutated. /* 即便值相同,拥有Deep属性的观察者以及在对象/数组上的观察者应该被触发更新,因为它们的值可能发生改变。 */ isObject(value) || this.deep ) { // set new value const oldValue = this.value /*设置新的值*/ this.value = value
/** * Evaluate the value of the watcher. * This only gets called for lazy watchers. */ /*获取观察者的值*/ evaluate () { this.value = this.get() this.dirty = false }
/** * Depend on all deps collected by this watcher. */ /*收集该watcher的所有deps依赖*/ depend () { let i = this.deps.length while (i--) { this.deps[i].depend() } }
/** * Remove self from all dependencies' subscriber list. */ /*将自身从所有依赖收集订阅列表删除*/ teardown () { if (this.active) { // remove self from vm's watcher list // this is a somewhat expensive operation so we skip it // if the vm is being destroyed. /*从vm实例的观察者列表中将自身移除,由于该操作比较耗费资源,所以如果vm实例正在被销毁则跳过该步骤。*/ if (!this.vm._isBeingDestroyed) { remove(this.vm._watchers, this) } let i = this.deps.length while (i--) { this.deps[i].removeSub(this) } this.active = false } } }
/** * A dep is an observable that can have multiple * directives subscribing to it. */ export default class Dep { static target: ?Watcher; id: number; subs: Array<Watcher>;
/*依赖收集,当存在Dep.target的时候添加观察者对象*/ depend () { if (Dep.target) { Dep.target.addDep(this) } }
/*通知所有订阅者*/ notify () { // stabilize the subscriber list first const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update() } } }
// the current target watcher being evaluated. // this is globally unique because there could be only one // watcher being evaluated at any time. Dep.target = null /*依赖收集完需要将Dep.target设为null,防止后面重复添加依赖。*/
/** * Define a reactive property on an Object. */ export function defineReactive ( obj: Object, key: string, val: any, customSetter?: Function ) { /*在闭包中定义一个dep对象*/ const dep = new Dep()