React渲染机制整理

核心思想

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结束执行的。

原文地址:https://www.cnblogs.com/moran1992/p/14731987.html