为了账号安全,请及时绑定邮箱和手机立即绑定

ReactDom.render学习笔记

标签:
React.JS

最近在学习React 源码深度解析 高级前端工程师必备技能》https://s.imooc.com/SUq8J2i

源码部分其中一节讲了ReactDom.render()创建更新。
整理如下 MarkDown使用不是很熟练将就看

第一部分 创建ReactRoot

  1. ReactDom.render()
    ReactDom.render()接受3个参数,elementcontainercallback
    返回下方代码的执行结果。
    legacyRenderSubtreeIntoContainer( null, element,container, false,callback)


  2. legacyRenderSubtreeIntoContainer

    legacyRenderSubtreeIntoContainer接收5个参数:

    (parentComponentchildrencontainerforceHydratecallback)

    在这个方法中 定义

    root = container.reactRootContainer =
    legacyCreateRootFromDOMContainer(container, forceHydrate,)

    通过 new React()*创建ReactRoot对象的方法下面有说明 *

    执行

    root.render (children, callback)

    也就是

    container.reactRootContainer.render(children, callback);

    最后返回

    return DOMRenderer.getPublicRootInstance(root._internalRoot) 返回实例

    由上文legacyCreateRootFromDOMContainer(container, forceHydrate,)方法创建添加的属性_internalRoot


  3. legacyCreateRootFromDOMContainer创建返回ReactRoot

    	
    function legacyCreateRootFromDOMContainer(
        container: DOMContainer,
        forceHydrate: boolean, // 是否复用已有子节点
      ): Root {
        /*  不重要 忽略
        const shouldHydrate =
          forceHydrate || shouldHydrateDueToLegacyHeuristic(container)
        // First clear any existing content.
        if (!shouldHydrate) {
          let warned = false
          let rootSibling
          while ((rootSibling = container.lastChild)) {
            container.removeChild(rootSibling)
          }
        }
        */
        // Legacy roots are not async by default.
        const isConcurrent = false
        
        return new ReactRoot(container, isConcurrent, shouldHydrate) // 创建ReactRoot
      }
      
      function ReactRoot(
        container: Container,
        isConcurrent: boolean,
        hydrate: boolean,
      ) {
      // 这个root 不是上面的 root
        const root = DOMRenderer.createContainer(container, isConcurrent, hydrate)
        this._internalRoot = root
      }
    

    也就是说
    ReactRoot._internalRoot// 内部本质root
    其实等于
    DOMRenderer.createContainer(container, isConcurrent, hydrate)

    结合
    上面的2. legacyRenderSubtreeIntoContainer
    root
    = container.reactRootContainer
    =legacyCreateRootFromDOMContainer(container, forceHydrate)
    = => new ReactRoot

省略中间步骤 root <=> new ReactRoot()


结合function ReactRoot

root._internalRoot 也其实就是 DOMRenderer.createContainer(container, isConcurrent, hydrate)返回,一个 FiberRoot

也就是说 上面2. legacyRenderSubtreeIntoContainer 实际上创建了一个 ReactRoot 并返回其公共根实例(getPublicRootInstance)

return DOMRenderer.getPublicRootInstance(root._internalRoot) 返回实例

整理

  1. root = container.reactRootContainer new ReactRoot() // ReactRoot
    1.1 root._internalRoot=DOMRenderer.createContainer(container, isConcurrent, hydrate))
    1.1.1 DOMRenderer.createContainer=>创建FiberRoot
  2. 也就是说 root.internalRoot 为 一个FiberRoot实例。 root的本质是FiberRootinternal中文为 (本质、内部)
  3. DOMRenderer.getPublicRootInstance(root._internalRoot) // 接收一个FiberRoot返回其公共根实例
  4. 整个过程是建立
    4.1 root为一个ReactRoot
    4.2 root._inernalRoot为一个FiberRoot,
    4.3 ReactRoot还有render方法也是第二部分的开始;

第二部分

  1. ReactRoot.render()主要执行 DOMRenderer.updateContainer(children, root, null, work._onCommit)
    其中root实际上为第一部分的ReactRoot._ineralRoot也就是FiberRoot,
    work._onCommit实际上为最开始传入的callback


  2. updateContainer()

    function updateContainer(
      element: ReactNodeList,
      container: OpaqueRoot,
      parentComponent: ?React$Component<any, any>,
      callback: ?Function,
    ): ExpirationTime {
      const current = container.current
      const currentTime = requestCurrentTime()
      
      // 计算更新超时时间
      const expirationTime = computeExpirationForFiber(currentTime, current)	  
      // 用超时时间来更新。
      return updateContainerAtExpirationTime(
        element,
        container,
        parentComponent,
        expirationTime,
        callback,
      )
    }
    

    updateContainerAtExpirationTime调用了scheduleRootUpdate

    function updateContainerAtExpirationTime(
      element: ReactNodeList,
      container: OpaqueRoot,
      parentComponent: ?React$Component<any, any>,
      expirationTime: ExpirationTime,
      callback: ?Function,
    ) {
      // TODO: If this is a nested container, this won't be the root.
      const current = container.current
      const context = getContextForSubtree(parentComponent)
      if (container.context === null) {
        container.context = context
      } else {
        container.pendingContext = context
      }
    
      return scheduleRootUpdate(current, element, expirationTime, callback)
    }
    
  3. scheduleRootUpdate
    3.1生成一个update
    3.2添加到更新队列enqueueUpdate(current, update)
    3.3开始任务调度。 // 后续内容
    3.4返回expirationTime

感谢能坚持看到这里 给点建议吧。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
3
获赞与收藏
0

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消