React 页面是由组件组成的,从根组件直到叶组件,内部的组件数通过 Fiber 来保存并触发并发更新。页面的展示分为两部分,首先是初始化,所有组件首次展示,都要进行渲染,之后是更新流程,也就是页面产生了交互,需要某些组件出现状态变更,React 内部找到需要更新的组件并进行更新。本文从源代码的角度,对 React 的初始化以及更新过程进行梳理:
JSX编译
JSX 是一种 HTML 代码模板,JavaScript 引擎原生并不支持 JSX 语法,因此,运行时需要首先将 JSX 转为浏览器可以执行的 JS 代码。React 通过 Babel 插件 plugin-transform-react-jsx 将 JSX 装换为 JS,下图中 Bundle.js 中包含最终转换好的 JS。
createRoot
首先,绑定 Root 容器到 Dom 节点,所有 Root 下的组件全部展示在 Dom 节点下。createRoot -> createContainer -> createFiberRoot,最终返回的是 FiberRoot
render
firerNode 创建完成之后,调用 root.render,是整个App 渲染的入口。
updateContainer 中有 Lane 的概念,Lane 和优先级有关系,以后具体再看起什么作用
进入 scheduleFiber,调度 Fiber 任务
进入 performConcurrentWorkOnRoot,并发执行任务
进入 renderRootSync,同步渲染 Root
进入 workLoopSync,循环处理任务
进入 performUnitOfWork, 开始处理任务
进入 beginWork,渲染开始
开始创建 FiberNode
进入reconcileChildren,进行对比
进入处理单个节点逻辑
进入创建 Fiber 方法
通过上面的步骤,FiberTree创建完成。下面进入 Commit 阶段,回到performConcurrentWorkOnRoot,进入 finishConcurrentRender:
最终进入 commitMutationEffects,找到需要修改的节点
进入commitMutationEffectsOnFiber
递归处理所有子节点
处理最终渲染
Dom 节点操作
总结
React 渲染流程代码比较多,入口在 Root.render,并发执行 Render,同步执行 Commit。