Vue3 watch 的过程

Vue3 watch执行过程

Vue.watch(() => {
    console.log("watch OK!!!");
    app.querySelector('p').textContent = count.value;
});

调用watch

// 简化后
export function watch(effectOrSource, effectOrOptions,options) {
  if (isFunction(effectOrOptions)) {
  } else {
   // 执行这里
    return doWatch(effectOrSource, null, effectOrOptions)
  }
}

doWatch (代码有点长,直接说一下流程吧)


doWatch(source,cb,options){
    // source 为fn  其他 在这里都不重要

    // 1. 将source 处理成 getter
    // 2. 将getter 打包成
    // 3.通过effect 打包成一个订阅函数 即 runner 变量
    // 3.1 ps: effect 很重要 下面列出了函数代码
    // 4. 执行 scheduler (scheduler是判断flush得到的)
    let scheduler = job => {
      queuePostRenderEffect(job, suspense)
    }
    // 5.执行 queuePostRenderEffect 后 会将函数添加到队列并执行它 
    // 5.1 `下面列出了这个函数`
    // 6.end 这个函数的事情做完了
}

// 这个函数会执行queuePostFlushCb然后将订阅函数放入(任务)队列
function queuePostRenderEffect(fn,suspense){
if (suspense !== null && !suspense.isResolved) {
   // 不重要
  } else {
    // 执行 queuePostFlushCb 
    queuePostFlushCb(fn)
  }
}
// 这个函数最大的功能就是 执行nextTick和添加队列
function queuePostFlushCb(cb: Function | Function[]) {
    // ...
    // 一些不重要的代码
    // ...
    // isFlushing不重要 最终会 执行 nextTick
      if (!isFlushing) {
        nextTick(flushJobs)
      }
}
// 异步执行函数
function nextTick(fn?: () => void) {
    return fn ? p.then(fn) : p
}

effect 函数(订阅函数)

effect( fn,options) {
    // ...
    // 一些不重要的代码
    // ...
    // 创造一个 effect对象 用于绑定一些属性和不允许重复绑定
    const effect = createReactiveEffect(fn, options)
    // ...
    // 一些不重要的代码
    // ...
    return effect
}

// 创建订阅函数
function createReactiveEffect(fn, options) {

    const effect = function effect(...args) {
        // run 函数 下面贴了代码
        return run(effect as ReactiveEffect, fn, args)
    }

    effect.isEffect = true
    effect.active = true
    effect.raw = fn
    effect.scheduler = options.scheduler
    effect.onTrack = options.onTrack
    effect.onTrigger = options.onTrigger
    effect.onStop = options.onStop
    effect.computed = options.computed
    effect.deps = []
    return effect
}

run 函数 (大概的理解,如有问题麻烦了)

// 将订阅函数添加到 等待队列后,执行fn函数
// 如果fn中有 可触发的data getter 就将函数订阅到该发布者 // 这里不知道怎么说了

function run(effect: ReactiveEffect, fn: Function, args: any[]): any {
  // 当 active 被停止 就不需要了订阅了 直接绑定即可
  if (!effect.active) {
    return fn(...args)
  }
  // 如果队列中不存在就表示此effect可以被订阅
  if (activeReactiveEffectStack.indexOf(effect) === -1) {
    cleanup(effect)
    try {
      // 先将 effect 添加到 等待订阅的队列
      activeReactiveEffectStack.push(effect)
      // 执行之后会触发getter 然后将effect订阅到队列
      return fn(...args)
    } finally {
      // 当订阅之后就退出来
      activeReactiveEffectStack.pop()
    }
  }
}

发表评论

请先登陆