ReactDOM.render串联渲染链路(二)

简介: 前一篇文章ReactDOM.render串联渲染链路(一),我们梳理了渲染链路的初始化阶段和render阶段的前半段,这篇文章我们来看看render阶段的后半段和commit阶段。

网络异常,图片无法展示
|


前言


前一篇文章ReactDOM.render串联渲染链路(一),我们梳理了渲染链路的初始化阶段和render阶段的前半段,这篇文章我们来看看render阶段的后半段和commit阶段。


render后半段


completeWork

前面有说道,在render阶段,这个过程中,穿插了大量了beginWork、completeWork调用,这两个方法串联起来就是一个模拟递归的过程。这个两个方法就是render的工作内容。接下来我们来看看completeWork。

网络异常,图片无法展示
|


在这render整个阶段beginWork和completeWork基本都是成对存在的,beginWork负责Fiber节点的创建,而competeWork负责Fiber阶段转换为真实Dom。

completeWork:前

网络异常,图片无法展示
|

if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
    startProfilerTimer(unitOfWork);
    // 创建当前节点的子节点
    next = beginWork(current, unitOfWork, subtreeRenderLanes);
    stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
  } else {
    // 创建当前节点的子节点
    next = beginWork(current, unitOfWork, subtreeRenderLanes);
  }
if (next === null) {
    // 调用 completeUnitOfWork
    completeUnitOfWork(unitOfWork);
  } else {
    // 将当前节点更新为新创建出的 Fiber 节点
    workInProgress = next;
  }


performUnitOfWork中,先通过beginWork来创建当前页面的子节点,然后判断创建的子阶段是否为空,如果为空(说明这个节点没有子节点, 是一个叶子节点)。因此这种情况下,就会调用 completeUnitOfWork,执行当前节点对应的 completeWork 逻辑。

completeWork:后

网络异常,图片无法展示
|

completeWork中和beginWork的执行如出一辙,根据workInProgress tag(一共有十余种)的不同,执行不同的逻辑。这里我们重点来看看HostComponent case:

网络异常,图片无法展示
|


其实在render过程中,存在两棵树,一颗就是大名鼎鼎的workInProgress树,一颗就是current树。这两棵树workInProgress树表示”当前正在render的树“,current树表示”已经render完成的树“。


workInProgress 节点和 current 节点之间用 alternate 属性相互连接。在组件的挂载阶段,current 树只有一个 rootFiber 节点,并没有其他内容


completeWork总结
  • completeWork目的:将Fiber映射为真实DOM
  • completeWork关键工作
  • 创建DOM
  • 插入DOM树
  • 设置DOM属性

completeUnitOfWork:开启大循环

网络异常,图片无法展示
|


completeUnitOfWork主要的作用是开启一个大循环,在里面循环如下的操作:

  1. 针对当前阶段,调用completeWork
  2. 将当前节点的副作用链(EffectList)插入到其父节点对应的副作用链(EffectList)中。
  3. 以当前节点为起点,循环遍历其兄弟节点及其父节点,当遍历到兄弟节点时,将 return 掉当前调用,触发兄弟节点对应的 performUnitOfWork 逻辑;而遍历到父节点时,则会直接进入下一轮循环,也就是重复 1、2 的逻辑。

在整个ReactDOM.render的过程中,render节点是最为重要的,也是最难理解的,我感觉熟悉知道就行。


commit 阶段


网络异常,图片无法展示
|


commit 分为三个阶段

  • before mutation
  • mutation
  • layout

before mutation

before mutation 阶段,这个阶段 DOM 节点还没有被渲染到界面上去,过程中会触发 getSnapshotBeforeUpdate,也会处理 useEffect 钩子相关的调度逻辑。


mutation

这个阶段负责 DOM 节点的渲染。在渲染过程中,会遍历 effectList,根据 flags(effectTag)的不同,执行不同的 DOM 操作。


layout

这个阶段处理 DOM 渲染完毕之后的收尾逻辑。比如调用 componentDidMount/componentDidUpdate,调用 useLayoutEffect 钩子函数的回调等。除了这些之外,它还会把 fiberRoot 的 current 指针指向 workInProgress Fiber 树。


总结


通过两篇文章大致的梳理了一下,ReactDOM.render的渲染链路。

  • 初始化阶段
  • render阶段
  • commit阶段

完成了对 ReactDOM.render 调用栈的分析。表面上剖析的是首次渲染的渲染链路,实际上将包括同步模式下的挂载、更新链路(与挂载链路的调用栈非常相似)都串联了一遍。

目录
相关文章
vue3渲染函数(h函数)的变化
vue3渲染函数(h函数)的变化
|
4月前
|
缓存 前端开发
useMemo问题之提高组件第一次渲染的速度如何解决
useMemo问题之提高组件第一次渲染的速度如何解决
|
4月前
|
移动开发 JavaScript 前端开发
VUE实现一个列表清单【props 父子组件通信、slot插槽的使用、全局自定义指令的封装、$nextTick解决异步DOM更新、巧用v-model简化父子组件之间的通信、触发事件的事件源event】
VUE实现一个列表清单【props 父子组件通信、slot插槽的使用、全局自定义指令的封装、$nextTick解决异步DOM更新、巧用v-model简化父子组件之间的通信、触发事件的事件源event】
42 0
|
6月前
|
存储 前端开发 JavaScript
在回调函数中重新渲染React组件
在React中,重新渲染组件可通过`forceUpdate()`或`ReactDOM.render()`实现。方法一是使用`forceUpdate`强制无状态组件更新;方法二是通过重新创建根组件实例适用于有状态组件。这些示例基于Webpack和Babel的模块热替换配置。根据项目需求和React版本,还可以结合React-Router或Redux等库选择合适的方法。
|
6月前
|
JavaScript 开发者
Teleport传送:使用Vue的Teleport进行跨DOM结构渲染
【4月更文挑战第24天】Vue.js的`<teleport>`组件用于跨DOM结构渲染,解决组件视觉呈现跨越父组件DOM的问题。它允许子组件内容传送到DOM的任意位置,如示例中将模态框移到`modal-container`元素。通过`target`属性指定目标元素,结合`v-if`控制显示,实现灵活的UI布局和交互。在适当场景下使用`<teleport>`能优化复杂应用的结构。
75 3
|
6月前
|
存储 缓存 JavaScript
|
前端开发
React-组件-Transition回调函数和React-组件-受控组件
React-组件-Transition回调函数和React-组件-受控组件
59 0
React-组件-Transition回调函数和React-组件-受控组件
|
前端开发 JavaScript 算法
为什么改变react状态,会触发组件重新渲染?
为什么改变react状态,会触发组件重新渲染?
142 2
|
前端开发
react +Antd Cascader级联选择使用接口数据渲染
react +Antd Cascader级联选择使用接口数据渲染
174 0
|
前端开发 JavaScript
react如何实现数据渲染
react如何实现数据渲染
163 0