1. 每个watch属性会创立观察者(Watcher实例),依据属性名(例如person.name)生成获取属性值的办法并保留在观察者的getter变量上,属性值变动后的调用函数也会被保留在观察者的cb变量上。观察者初始化时调用getter函数,读取watch监听的数据(响应式数据),通过数据属性定义的get将观察者增加到值的依赖收集器中。
var Watcher = function Watcher (  vm,  expOrFn,  cb,  options,  isRenderWatcher) {  this.vm = vm;  ...  this.cb = cb;  ...  if (typeof expOrFn === 'function') {    this.getter = expOrFn;  } else {    this.getter = parsePath(expOrFn);// 依据属性名生成获取属性值的办法    ...  }  this.value = this.lazy    ? undefined    : this.get();};
// 解析属性名function parsePath (path) {  if (bailRE.test(path)) {    return  }  var segments = path.split('.');  return function (obj) {    for (var i = 0; i < segments.length; i++) {      if (!obj) { return }      obj = obj[segments[i]];    }    return obj  }}
  1. 当监听值发生变化时,将调用收集的watch观察者的更新办法,执行queueWatcher(this),将观察者增加到队列(微工作)中,在nextTick中执行观察者的cb办法(watch属性值变动后的调用函数)。
Watcher.prototype.update = function update () {  /* istanbul ignore else */  if (this.lazy) {    this.dirty = true;  } else if (this.sync) {    this.run();  } else {    queueWatcher(this);//  }};
function queueWatcher (watcher) {  var id = watcher.id;  if (has[id] == null) {    has[id] = true;    if (!flushing) {// 处于收集watcher状态,未执行watcher办法      queue.push(watcher);// 将    } else {// 正在执行收集的watcher的更新办法      // if already flushing, splice the watcher based on its id      // if already past its id, it will be run next immediately.      var i = queue.length - 1;      while (i > index && queue[i].id > watcher.id) { // 插入到以后正在解决的wacher前面,且正好id要大于后面id        i--;      }      queue.splice(i + 1, 0, watcher); // 依据id大小插入到未解决的watch外面    }    // queue the flush    if (!waiting) {      waiting = true;      if (process.env.NODE_ENV !== 'production' && !config.async) {        flushSchedulerQueue();        return      }      nextTick(flushSchedulerQueue);    }  }}