}
else {
break;
}
{
const now = getNow();
if (now - flushStartTimestamp > frameBudget && job.expiration > now) {
break; // 此处为关键,意思是超过16ms,或者任务过期,跳出循环
}
}
}
... 以下代码省略...
上面的循环很关键,它做的事情很简单的,从 stageQueue 里出栈一个任务,然后执行 stateJob
stateJob 做的事情很简单,就是往 commitQueue 里 push 这个任务
function stageJob(job) {
if (job.ops.length === 0) {
currentJob = job;
job.cleanup = job();
currentJob = null;
commitQueue.push(job); //重点在这里
job.status = 2;
}
}
到目前为止,我们源码读了一丢丢,但是已经几乎读完了可以说
它的本质就是,在宏任务中,stageQueue 作为低优先级任务队列,不断的出栈,然后分批次(16ms 的阈值)入栈到 commitQueue 里
呼,其实如果不是写文章,就可以到此为止了,但是写文章为了凑字数嘛,我们继续
上面我们已经知道了两个队列,stageQueue 和 commitQueue,但是并不知道他们里面都是什么东西
是什么东西被调度的呢?打印一下,你就知道:
console.log(stageQueue,commitQueue)得出的结果是
function mountComponentInstance(){...}看名字就知道是组件挂载函数,当然组件更新和卸载的函数也是同理
到现在,我们也知道了参与调度的是组件挂载更新的函数,所以本质上,vue 的时间切片的基本单位是组件,也就是说,如果你的组件挂载需要一个小时,那你仍然要卡一小时
凑字数
剩下的内容纯属凑字数,就是除了核心调度之外的东西
比如 commitQueue 是操作 dom 的,那它咋个操作
function commitJob(job) {
const { ops, postEffects } = job;
for (let i = 0; i < ops.length; i++) {
applyOp(ops[i]); // 重点在这里
}
if (postEffects) {
postEffectsQueue.push(...postEffects);
}
resetJob(job);
job.status = 0;
}如上,拿到 ops,然后进行操作,我们看一下 ops 是啥就行了
[<div></div>, <li></li>, function CreactElement(){}]凑合凑合,是个数组,包含了 dom 操作的方法和被操作的元素
然后这个过程是同步完成的,也就是所谓的高优先级任务,必须等到彻底收集完毕,才可以循环执行它
做完这个,postEffectQueue 主要是一些额外的副作用和清理工作,我实在凑字数无能,就不打印了










