functioninitComputed (vm, computed) { // $flow-disable-line var watchers = vm._computedWatchers = Object.create(null); // computed properties are just getters during SSR var isSSR = isServerRendering();// 判断是否是服务器端渲染
for (var key in computed) { var userDef = computed[key]; var getter = typeof userDef === 'function' ? userDef : userDef.get; if (getter == null) { warn( ("Getter is missing for computed property \"" + key + "\"."), vm ); }
if (!isSSR) { // create internal watcher for the computed property. watchers[key] = newWatcher( vm, getter || noop, noop, computedWatcherOptions ); }
// component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. if (!(key in vm)) { defineComputed(vm, key, userDef); } else { if (key in vm.$data) { warn(("The computed property \"" + key + "\" is already defined in data."), vm); } elseif (vm.$options.props && key in vm.$options.props) { warn(("The computed property \"" + key + "\" is already defined as a prop."), vm); } } } }
/** * Depend on all deps collected by this watcher. */ Watcher.prototype.depend = functiondepend () { var i = this.deps.length; while (i--) { this.deps[i].depend(); } };
/** * Evaluate the getter, and re-collect dependencies. */ Watcher.prototype.get = functionget () { pushTarget(this); var value; var vm = this.vm; try { value = this.getter.call(vm, vm); } catch (e) { if (this.user) { handleError(e, vm, ("getter for watcher \"" + (this.expression) + "\"")); } else { throw e } } finally { // "touch" every property so they are all tracked as // dependencies for deep watching if (this.deep) { traverse(value); } popTarget(); this.cleanupDeps(); } return value };
<!--在getter函数中代码--> if (Dep.target) { dep.depend(); if (childOb) { childOb.dep.depend(); } if (Array.isArray(value)) { dependArray(value); } } Dep.prototype.depend = function depend () { if (Dep.target) { Dep.target.addDep(this); } };
Watcher.prototype.addDep = function addDep (dep) { var id = dep.id; if (!this.newDepIds.has(id)) { this.newDepIds.add(id); this.newDeps.push(dep); if (!this.depIds.has(id)) { dep.addSub(this); } } };
Dep.prototype.notify = functionnotify () { // stabilize the subscriber list first var subs = this.subs.slice(); if (!config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they fire in correct // order subs.sort(function (a, b) { return a.id - b.id; }); } for (var i = 0, l = subs.length; i < l; i++) { subs[i].update(); } }; /** * Subscriber interface. * Will be called when a dependency changes. */ Watcher.prototype.update = functionupdate () { /* istanbul ignore else */ if (this.lazy) { this.dirty = true; } elseif (this.sync) { this.run(); } else { queueWatcher(this); } };