触发更新时watcher的执行

  • watcher分为三种,Computed Watcher, 用户Watcher侦听器,渲染Watcher
  • 前两种 initState 时初始化
  • 渲染watcher在 core/instance/lifecycle.js 中 mountComponent,后执行
  • 当调用 dep.notify 时,会对watcher排序,而后顺次更新watcher.update
  • 对于不同类型 watcher, update解决形式不同
  • 渲染watcher会判断 以后组件watcher是否放入队列中,未放入 则找到地位插入到队列中
  • 调用 flushSchedulerQueue 办法

    • 先更新父组件后更新子组件(父组件先创立)
    • 用户watchers在渲染watcher之前运行,(用户或计算属性在initState中创立,在mountComponent之前)
    • 如果一个组件在父组件执行期间被销毁,则跳过以后组件
    • 遍历队列中的 watcher,调用 watcher.run()
    • run 办法内 调用get 办法, get办法调用 了 this.getter.call(vm, vm)
    • this.getter 就是 updateComponent 办法
  • 更新完结后重置状态
  • 调用 activated,updated两个钩子

    notify () {// copyconst subs = this.subs.slice()if (process.env.NODE_ENV !== 'production' && !config.async) {  // 按watcher的创立程序排序  subs.sort((a, b) => a.id - b.id)}// 调用 watcher的 更新for (let i = 0, l = subs.length; i < l; i++) {  subs[i].update()}}
    update () {// 三种watcher update 渲染watcher 走elseif (this.lazy) {  this.dirty = true} else if (this.sync) {  this.run()} else {  queueWatcher(this)}}
    export function queueWatcher (watcher: Watcher) {const id = watcher.id// has是个对象,避免 watcher被反复解决if (has[id] == null) {  has[id] = true  // flushing = true 示意 watcher对象正在被解决  // 把watcher放入队列中  if (!flushing) {    queue.push(watcher)  } else {    let i = queue.length - 1    // 队列未解决完,从后向前取watcher和以后组件watcher比拟,确定i    while (i > index && queue[i].id > watcher.id) {      i--    }        // 把组件watcher插入对应地位    queue.splice(i + 1, 0, watcher)  }    // waiting = true 示意 以后队列正在执行  if (!waiting) {    waiting = true    if (process.env.NODE_ENV !== 'production' && !config.async) {      // 遍历所有watcher,调用 watcher.run()      flushSchedulerQueue()      return    }    // 生产环境会传入nextTick,    nextTick(flushSchedulerQueue)  }}}
    function flushSchedulerQueue () {... // 把watcher插入队列// 遍历队列内的watcher执行 runwatcher.run()...}
    run () {...this.get() // this指watcher...}
    get () {  pushTarget(this)...// this.getter 为 updateComponentvalue = this.getter.call(vm,vm)}