react16架构的变化
react api的变化就不说了。react架构从stack变到了“fiber”。 最大的变化就是支持了任务帧,把各个任务都增加了优先级,同步和异步。比如用户输入input是优先级比较高的,它可以打断低优先级的任务。 比如再处理dom diff的时候耗时严重,fiber任务处理大概会有50ms的帧时长,超过这个时间就会先去看看有没高优任务去做。然后回来做低优先级任务。
优先级高的任务可以中断低优先级的任务。然后再重新,注意是重新执行优先级低的任务。 还增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行。(不过用户操作默认是同步的,暂时还没开放这个特性) dom diff树变成了链表,一个dom对应两个fiber(一个链表),对应两个队列,这都是为找到被中断的任务,重新执行而设计的。 设计成链表之后就更方便了。递归改循环,结点关系更好维护了,看下图就一目了然。
performWork
这里会开始任务的处理,调度完成。 performWork的作用就是“刷新”待更新队列,执行待更新的事务。 处理逻辑主循环是workLoop,也会调用一次scheduleDeferredCallback,未来处理一次更新,来完成workLoop未完成的任务。
workLoop
如果没有alternate fiber首先会根据update queue创建fiber,进入的是createWorkInProgress函数。createWorkInProgress 这个函数会构建一颗树的顶端,赋值给全局变量 nextUnitOfWork ,通过迭代的方式,不断更新 nextUnitOfWork 直到遍历完所有树的节点。
然后就会处理帧任务,进入函数首要处理就是看下上次处理有没有没被处理的任务,然后根据时间片处理任务。 如果任务在deadline之前没有commit,就会被标记pendingCommit,workLoop首先会处理pendingCommit。 接下来是处理逻辑:
如果下一个update是同步的,就调用performUnitOfWork进行reconcilation,最后调用commitAllWork把它渲染到dom。 解决完同步的任务,这时候看下时间片,有没有超时,如果没有,调用performUnitOfWork执行异步任务。 如果还有时间就commitAllWork,如果没有时间就留到下一帧提交。
performUnitOfWork
performUnitOfWork是执行的reconcilation阶段,它又拆分成beginWork和complete,beginWork做的是产出effect list,complete做的是处理react实例的生命周期和处理属性等操作。
fiber 目的
- 中断进程,后面还可以回到进程(work)中;
- 为各个进程(work)分优先级;
- 可以再次使用之前完成的进程(work);
- 终止后面不再使用的进程(work);