核心思想
ReactElement
Fiber
Current tree and Progress tree
ReactElement
什么是ReactElement,jsx通过babel转化成React.createElement创造出来的数据结构,也就是通常所说的虚拟dom的数据结构(对象)
该数据结构通过$$typeof标识一个React元素,并且还有其他属性props,key,ref等,最终以type表述该元素
Fiber
什么是Fiber节点,fiber概念是react在16版本之后增加的一个思想。
Fiber的诞生解决了react渲染到页面出现的卡顿问题,新的渲染机制解决这个问题,但是旧的dom机制没办法实现。
在React中,每一个组件都会经历create.CreateElement转化成为ReactElement,在通过对每一个组件ReactElement生成了一个对应的Fiber节点,而这些节点将会
以链表的形式存放,形成了一个fiber节点的树
Current true and Workinprogress tree
Fiber树分为两种,一种是当前页面的树,就是current tree,另外一颗树是更新时候的生成的,根据当前current tree以及修改的一些参数生成的叫workInprogress树
最终将workInProgress树更新到页面上,渲染之后此时的workInprogress树变成current树
React的渲染流程分为两个阶段
1.render阶段
render阶段开始是从renderRoot开始,在这个阶段之前,是对fiber节点的初始化,初始化的根fiber节点含有firstUpdate,fristUpdate中element就是App的ReactElement
在React渲染过程中,整个fiber树是从workLoop函数循环创建出来的
整个过程是深度遍历
有兄弟节点,返回兄弟节点放入到workloop中进行循环
没有兄弟节点,修改workInprogress树的指向,指向当前fier节点的父级
没有父级没有兄弟节点,返回null workloop执行结束
整个过程生成workInprogress树(已经更新的树)同时生成一个effectList链表(收集变化的虚拟dom)
(ps:整个遍历生成workInprogress过程中同时会标记副作用fiber node,effectlist会收集这些fiber node,effectlist在提交阶段会映射到真是dom)
fiber之前的方案
因为fiber是采用链表结构,遍历过程采用二叉树深度优先遍历复杂度(O(Log2|n)和O(n)之间,如果是平衡二叉树则是O(Log2|n),从而达到了优化的对比的过程,而在老的版本,是采用递归方式遍历两颗树复杂度(n)
递归的复杂度的由来是由于采用优化机制,即element diff component diff tree diff
2.commit阶段
执行完render阶段,现在会有两颗树,current 树根workInprogress树
在commit阶段会执行commitRoot函数,所有的生命周期,新增,删除,更新组件都是在commitRoot中实现
commit阶段主要工作是对真实dom的修改
更新dom不会重新遍历整颗树,而是通过循环整个effectlist链表来实现的,这样保证了只针对变化的dom工作
commit三个阶段
before mutation:读取组件变更前的状态class (getSnopshotBeforeUpdate)function(userEffect)
mutation:针对hostCompont进行相应操作,class(componentWillUnmunt)function (useEffect销毁)
layout:操作dom完成之后class(componentDidMount)
workInprogress 树切换到current树也是在commit结束执行的。