最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • ReactDOM.render串联渲染链路(一)

    正文概述 掘金(拜小白)   2021-02-23   757

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


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

    ReactDOM.render 调用栈


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

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

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

    初始化阶段


    完成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阶段


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

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

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

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

    performSyncWorkOnRoot:开始render阶段

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

    renderRootSync:准备工作

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

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

    ReactDOM.render串联渲染链路(一) 这里比较重要的是调用了createWorkInProgress这个函数,我们来看看这个函数干了什么

    createWorkInProgress

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

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

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

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

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

    beginWork:创建Fiber节点

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

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

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

    Fiber 节点间是如何连接

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

    后续


    下一章继续为大家来分享ReactDOM.render串联渲染链路
    感谢修言大神的《深入浅出搞定 React》

    起源地下载网 » ReactDOM.render串联渲染链路(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元