前置知识
在阅读源码过程中遇到一些技术点,在这里先总结下。
1.链表
链表的分类: 单向链表,双向链表,循环链表
2.树的遍历: 前序遍历,中序遍历,后序遍历
这里的树的遍历指二叉树的遍历,在刷算法的时候经常见到。简单介绍下区别:
二叉树的遍历 主要分为前序遍历、中序遍历、后序遍历。他们之间的区别在于根节点(root)的结点遍历的顺序。 前序遍历就是先遍历根结点,再遍历左子树,最后遍历右子树; 中序遍历就是先遍历左子树,再遍历root结点,最后遍历右子树; 后序遍历就是先遍历左子树,再遍历右子树,最后遍历根结点
3.fiber的设计初衷
-
旧版本的更新: 递归更新,无法中断。递归更新比较久时,会造成卡顿。 浏览器的刷新频率60Hz,时间是16.6ms,js进程和渲染进行是互斥的,不能同时进行。
-
新版本的更新: 可中断异步更新,新的架构设计增加了Scheduler,是个单独的库,独立于React。
新的更新是React在浏览器空闲的时间去更新,不影响渲染进程的渲染,避免页面卡顿;把耗时的任务变成一个个小的执行单元,分布在每一帧里。
执行单元就是fiber。React使用MessageChannel来模拟requestIdlecallback,来检测剩余空闲时间,如果还有空闲时间就执行下一个fiber单元。
a. fiber是执行单元也是一种数据结构。
fiber结构包含三类型的数据:
- 节点的属性,如key,标签类型,
- 链表结构的指针: 如child,sibling,return
- fiber节点保存的数据: 如 memoizedState,updateQueue
//Fiber节点的数据属性
function FiberNode(tag, pendingProps, key) {
this.tag = tag;
this.key = key;
this.type = null; //fiber类型,来自于 虚拟DOM节点的type span div p
//每个虚拟DOM=>Fiber节点=>真实DOM
this.stateNode = null; //此fiber对应的真实DOM节点 h1=>真实的h1DOM
this.return = null; //指向父节点
this.child = null; //指向第一个子节点
this.sibling = null; //指向弟弟
//fiber通过虚拟DOM节点创建,虚拟DOM会提供pendingProps用来创建fiber节点的属性
this.pendingProps = pendingProps; //等待生效的属性
this.memoizedProps = null; //已经生效的属性
//每个fiber还会有自己的状态,每一种fiber 状态存的类型是不一样的
//类组件对应的fiber 存的就是类的实例的状态,HostRoot存的就是要渲染的元素
this.memoizedState = null;
//每个fiber身上可能还有更新队列
this.updateQueue = null;
//副作用的标识,表示要针对此fiber节点进行何种操作
this.flags = NoFlags; //自己的副作用
//子节点对应的副使用标识
this.subtreeFlags = NoFlags;
//`currentFiber`和`workInProgressFiber`,通过`alternate`来实现指向
this.alternate = null;
this.index = 0;
this.deletions = null;
this.lanes = NoLanes;
this.childLanes = NoLanes;
this.ref = null;
}
b. fiber架构的设计:双缓存设计currentFiber
和workInProgressFiber
,通过alternate
来实现指向连接。
当前页面显示的内容对应currentFiber
的内容,正在更新构建的是workInProgressFiber
fiber树。
当workInProgressFiber为null时,是初始化加载,创建currentFiber,更新时使用构建好的workInProgressFiber
去render,然后和currentFiber替换。 React内部保存两套fiber,来回替换。
4.更新优先级 :事件优先级,更新优先级,调度优先级。 优先级这里比较复杂,3类优先级的匹配关系后面会详细介绍。
- React中用lane(车道)模型来表示任务优先级
- 一共有31条优先级,数字越小优先级越高,某些车道的优先级相同
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3天,点击查看活动详情