image.png

image.png
image.png
image.png

  1. export function render(
  2. element: React$Element<any>,
  3. container: Container,
  4. callback: ?Function,
  5. ) {
  6. return legacyRenderSubtreeIntoContainer(
  7. null,
  8. element,
  9. container,
  10. false,
  11. callback,
  12. );
  13. }

render函数中调用了legacyRenderSubtreeIntoContainer

  1. function legacyRenderSubtreeIntoContainer(
  2. parentComponent: ?React$Component<any, any>, //null
  3. children: ReactNodeList,
  4. container: Container, //root
  5. forceHydrate: boolean, //false
  6. callback: ?Function,
  7. ) {
  8. // 初次调用, root还未初始化, 会进入此分支
  9. //1. 创建ReactDOMRoot对象, 初始化react应用环境
  10. let root = container._reactRootContainer;
  11. let fiberRoot: FiberRoot;
  12. if (!root) {
  13. // Initial mount
  14. console.log('render no root');
  15. root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
  16. container,
  17. forceHydrate,
  18. );
  19. fiberRoot = root;
  20. if (typeof callback === 'function') {
  21. const originalCallback = callback;
  22. callback = function() {
  23. const instance = getPublicRootInstance(fiberRoot);
  24. originalCallback.call(instance);
  25. };
  26. }
  27. // Initial mount should not be batched.
  28. // 2. 更新容器
  29. // 初次渲染是非批量更新,可以保证 ( 更新效率与用户体验 )
  30. // 比如初次渲染希望更快的速速让用户看到 ui
  31. // - 函数签名:flushSyncWithoutWarningIfAlreadyRendering(fn) => fn()
  32. flushSyncWithoutWarningIfAlreadyRendering(() => {
  33. updateContainer(children, fiberRoot, parentComponent, callback);
  34. });
  35. } else {
  36. console.log('render have root')
  37. // root已经初始化, 二次调用render会进入
  38. // 1. 获取ReactDOMRoot对象
  39. fiberRoot = root;
  40. if (typeof callback === 'function') {
  41. const originalCallback = callback;
  42. callback = function() {
  43. const instance = getPublicRootInstance(fiberRoot);
  44. originalCallback.call(instance);
  45. };
  46. }
  47. // Update
  48. // 2. 调用更新
  49. updateContainer(children, fiberRoot, parentComponent, callback);
  50. }
  51. return getPublicRootInstance(fiberRoot);
  52. }

image.png
render之后的调用过程如上图所示,
判断是否有root节点,创建rootFiber,FiberRoot等,节点之间的关系如下图所示:
image.png
updateContainer函数位于react-reconciler包中, 它串联了react-dom与react-reconciler.
此处暂时不深入分析updateContainer函数的具体功能, 需要关注其最后调用了scheduleUpdateOnFiber.

在前文reconciler 运作流程中, 重点分析过scheduleUpdateOnFiber是输入阶段的入口函数.

所以到此为止, 通过调用react-dom包的api(如: ReactDOM.render), react内部经过一系列运转, 完成了初始化, 并且进入了reconciler 运作流程的第一个阶段.

References

https://cloud.tencent.com/developer/article/1843869