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

stonehehehehehe 2021-02-23 10:26:21
渲染 render 串联 reactdom.render reactdom


学习串联渲染链路你能学到什么?


  • React 16 在所有情况下都是异步渲染的吗?
  • Fiber 架构中的“可中断”“可恢复”到底是如何实现的?
  • Fiber 树和传统虚拟 DOM 树有何不同?
  • 优先级调度又是如何实现的?

ReactDOM.render 调用栈


ReactDOM.render 调用栈大致可以拆分成如下三个阶段:

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

初始化阶段


完成Fiber树中基本实体的创建,哪什么是Fiber,它是干啥的,基本实体又是什么?

Fiber是什么?

Fiber是对React核心算法的重构。

Fiber的作用?
  • 把可中断的工作拆分小任务
  • 对正在操作的工作调整优先次序、重做、复用
  • 在父子任务之间切换,以支持React执行过程中的布局刷新
  • 支持render返回多个元素
基本实体是什么?

技基础实体想要了解他,来看一段源码

function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
// container 对应的是我们传入的真实 DOM 对象
var root = container._reactRootContainer;
// 初始化 fiberRoot 对象
var fiberRoot;
// DOM 对象本身不存在 _reactRootContainer 属性,因此 root 为空
if (!root) {
// 若 root 为空,则初始化 _reactRootContainer,并将其值赋值给 root
root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);
// legacyCreateRootFromDOMContainer 创建出的对象会有一个 _internalRoot 属性,将其赋值给 fiberRoot
fiberRoot = root._internalRoot;
// 这里处理的是 ReactDOM.render 入参中的回调函数,你了解即可
if (typeof callback === 'function') {
var originalCallback = callback;
callback = function () {
var instance = getPublicRootInstance(fiberRoot);
originalCallback.call(instance);
};
} // Initial mount should not be batched.
// 进入 unbatchedUpdates 方法
unbatchedUpdates(function () {
updateContainer(children, fiberRoot, parentComponent, callback);
});
} else {
// else 逻辑处理的是非首次渲染的情况(即更新),其逻辑除了跳过了初始化工作,与楼上基本一致
fiberRoot = root._internalRoot;
if (typeof callback === 'function') {
var _originalCallback = callback;
callback = function () {
var instance = getPublicRootInstance(fiberRoot);
_originalCallback.call(instance);
};
} // Update
updateContainer(children, fiberRoot, parentComponent, callback);
}
return getPublicRootInstance(fiberRoot);
}

在这段源码中主要的操作就是赋值fiberRoot对象,这个对象是通过root._internalRoot赋值,本质上这个对象是一个FiberRootNode对象,其中包含一个current对象,这个对象是FiberNode实例。而 FiberNode,正是 Fiber 节点对应的对象类型。current 对象是一个 Fiber 节点,不仅如此,它还是当前 Fiber 树的头部节点。其中,fiberRoot 的关联对象是真实 DOM 的容器节点;而 rootFiber 则作为虚拟 DOM 的根节点存在。这两个节点,将是后续整棵 Fiber 树构建的起点。

整个初始化的工作过程都是在为后续的 render 阶段做准备。现在,我们的 Fiber Tree 还处在只有根节点的起始状态。接下来,我们就要进入到最最关键的 render 阶段里去,一起去看看这棵树是怎么一点点开枝散叶的吧!

render阶段


scheduleUpdateOnFiber 方法的作用是调度更新,在由 ReactDOM.render 发起的首屏渲染这个场景下,它触发的就是 performSyncWorkOnRoot。performSyncWorkOnRoot 开启的正是我们反复强调的 render 阶段;finishSyncRoot标志着render方法的结束。在这个过程中,穿插了大量了beginWork、completeWork调用(这两个方法串联起来就是一个模拟递归的过程)。这个两个方法就是render的工作内容。

在React15中调和是一个递归的过程。在Fiber架构下,虽然不依赖递归,但是ReactDOM.render模式下,他整体是一个同步过程,是一个优先深度遍历。在这个过程中beginWork是负责创建Fiber节点,completeWork负责将Fiber节点映射为真实DOM。

接下来来看看这个过程有那些比较重要的调用

performSyncWorkOnRoot:开始render阶段

renderRootSync:准备工作

prepareFreshStack:重置一个新的堆栈环境


这里比较重要的是调用了createWorkInProgress这个函数,我们来看看这个函数干了什么

createWorkInProgress

workLoopSync:通过 while 循环反复判断 workInProgress 是否为空,并在不为空的情况下针对它执行 performUnitOfWork 函数。

performUnitOfWork:触发对beginWork的调用。performUnitOfWork,其主要工作是“通过调用 beginWork,来实现新 Fiber 节点的创建”;它还有一个次要工作,就是把新创建的这个 Fiber 节点的值更新到 workInProgress 变量里去。

beginWork:创建Fiber节点

beginWork 的核心逻辑是根据 fiber 节点(workInProgress)的 tag 属性的不同,调用不同的节点创建函数。在beginWork后面还有很多逻辑,感兴趣的同学可以深挖,借鉴网上的一张图如下:

Fiber 节点间是如何连接

不同的 Fiber 节点之间,将通过 child、return、sibling 这 3 个属性建立关系,其中 child、return 记录的是父子节点关系,而 sibling 记录的则是兄弟节点关系。FiberNode 实例中,return 指向的是当前 Fiber 节点的父节点,而 sibling 指向的是当前节点的第 1 个兄弟节点。

后续

下一章继续为大家来分享ReactDOM.render串联渲染链路
感谢修言大神的《深入浅出搞定 React》
版权声明
本文为[stonehehehehehe]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000039258179

  1. How to build a high performance front end intelligent reasoning engine
  2. How to become a professional front end engineer in 2021?
  3. How to transform single / micro service application into serverless application
  4. How to transform single / micro service application into serverless application
  5. How to transform single / micro service application into serverless application
  6. How to connect the ground gas to the micro front end?
  7. How to connect the ground gas to the micro front end?
  8. How to connect the ground gas to the micro front end?
  9. Vue server rendering principle analysis and introduction
  10. Realize the correct loading of text message
  11. Building my own project scaffolding with yeoman
  12. JavaScript advanced prototype and prototype chain
  13. React background management front end system (based on open source framework development) start
  14. JS practical skills breakpoint debugging
  15. I'd like to share with you 20 super easy-to-use Chrome extension plug-ins
  16. Get page element location
  17. Use the powerful API of modern browser to record any interface in the browser and realize export, save and management
  18. Delayed code execution in flutter
  19. Reconfiguration experience of KOA middleware system
  20. Add comments to your blog
  21. Svg editor -- new path
  22. Detailed explanation of debounce and throttle of JavaScript function
  23. Anti shake and throttling and corresponding react hooks package
  24. C2m: the first CSDN article moved to MOOC script 5000 words, detailed painstaking development process, there are renderings and source code at the end of the article
  25. Front end, school recruitment, Taobao, guide
  26. [vue2 & G6] get started quickly
  27. Canvas from the beginning to the pig
  28. Take five minutes to standardize the code comments?
  29. Some thoughts on sass
  30. what?! You haven't filled in the award information yet
  31. How to get the interface + tsdoc needed by TS through swagger
  32. Binary tree
  33. Canvas drawing method in Web screenshot
  34. Front end docker image volume optimization (node + nginx / node + multi-stage construction)
  35. Become a big influence of technology? Coding pages quickly build personal blog
  36. Object and array deconstruction, spread operator, rest operator
  37. Analysis of Axios source code
  38. Two ways to delete useless code in project (Practical)
  39. Edit your picture with canvas
  40. Today's chat: 2-4 years to walk out of the resignation dilemma and comfort zone
  41. JS mechanism 3: stack, heap, garbage collection
  42. [grid compression evaluation] meshquan, meshopt, Draco
  43. Deep understanding of Vue modifier sync [Vue sync modifier example]
  44. WebView for front end engineers
  45. React form source code reading notes
  46. Deep thinking about modern package manager -- why do I recommend pnpm instead of NPM / yarn?
  47. On the sequence of event capture and event bubbling
  48. Help you build a systematic understanding of the front end scaffolding
  49. commander.js Principle analysis
  50. Common usage of nginx
  51. H5 jump to wechat app
  52. Front end algorithm interview must brush questions series [14]
  53. Thinking of cross end practice
  54. Vue server rendering principle analysis and introduction
  55. [KT] vscode plug in development example series (2)
  56. Design ideas of react and Vue framework
  57. JavaScript String.prototype.replaceAll 兼容性导致的问题
  58. JavaScript String.prototype.replaceAll Problems caused by compatibility
  59. 爱奇艺体育:体验Serverless极致扩缩容,资源利用率提升40%
  60. Iqiyi Sports: experience the ultimate expansion and contraction of serverless, and increase the utilization rate of resources by 40%