React16源码: React中的completeWork对HostText处理含更新的源码实现

news/2024/7/15 18:40:23 标签: react.js, 前端, 前端框架

HostText


1 )概述

  • completeWork 中 对 HostText的处理
  • 在第一次挂载和后续更新的不同条件下进行操作
    • 第一次挂载主要是创建实例
    • 后续更新其实也是重新创建实例

2 )源码

定位到 packages/react-reconciler/src/ReactFiberCompleteWork.js#L663

case HostText 这里

case HostText: {
  let newText = newProps;
  // 符合这个条件,说明它不是第一次渲染,就是更新的状态
  // 调用 updateHostText 进行更新
  if (current && workInProgress.stateNode != null) {
    const oldText = current.memoizedProps;
    // If we have an alternate, that means this is an update and we need
    // to schedule a side-effect to do the updates.
    updateHostText(current, workInProgress, oldText, newText);
  } else {
    // 对于第一次渲染
    if (typeof newText !== 'string') {
      invariant(
        workInProgress.stateNode !== null,
        'We must have new props for new mounts. This error is likely ' +
          'caused by a bug in React. Please file an issue.',
      );
      // This can happen when we abort work.
    }
    // 跳过 context 处理
    const rootContainerInstance = getRootHostContainer();
    const currentHostContext = getHostContext();
    // 跳过 hydrate 处理
    let wasHydrated = popHydrationState(workInProgress);
    if (wasHydrated) {
      if (prepareToHydrateHostTextInstance(workInProgress)) {
        markUpdate(workInProgress);
      }
    } else {
      // 创建 文本 实例
      workInProgress.stateNode = createTextInstance(
        newText,
        rootContainerInstance,
        currentHostContext,
        workInProgress,
      );
    }
  }
  break;
}
  • 进入 updateHostText

    updateHostText = function(
      current: Fiber,
      workInProgress: Fiber,
      oldText: string,
      newText: string,
    ) {
      // 这个非常简单,通过前后 text 是否有区别
      // 如果不同,则创建新的 text实例
      if (oldText !== newText) {
        // If the text content differs, we'll create a new text instance for it.
        // 先跳过 context 的处理
        const rootContainerInstance = getRootHostContainer();
        const currentHostContext = getHostContext();
        workInProgress.stateNode = createTextInstance(
          newText,
          rootContainerInstance,
          currentHostContext,
          workInProgress,
        );
        // We'll have to mark it as having an effect, even though we won't use the effect for anything.
        // This lets the parents know that at least one of their children has changed.
        markUpdate(workInProgress);
      }
    };
    
    • 进入 createTextInstance
      // packages/react-dom/src/client/ReactDOMHostConfig.js#L272
      export function createTextInstance(
        text: string,
        rootContainerInstance: Container,
        hostContext: HostContext,
        internalInstanceHandle: Object,
      ): TextInstance {
        if (__DEV__) {
          const hostContextDev = ((hostContext: any): HostContextDev);
          validateDOMNesting(null, text, hostContextDev.ancestorInfo);
        }
        const textNode: TextInstance = createTextNode(text, rootContainerInstance);
        // 这个方法之前阅过
        precacheFiberNode(internalInstanceHandle, textNode);
        return textNode;
      }
      
      • 进入 createTextNode
        export function createTextNode(
          text: string,
          rootContainerElement: Element | Document,
        ): Text {
          // 最终 getOwnerDocumentFromRootContainer 这里返回一个dom对象,调用dom的 createTextNode 这个方法
          return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(
            text,
          );
        }
        
        • 进入 getOwnerDocumentFromRootContainer
        function getOwnerDocumentFromRootContainer(
          rootContainerElement: Element | Document,
        ): Document {
          // rootContainerElement.ownerDocument 这里是 window.document 对象
          // 这么做是为了兼容多平台api的使用
          return rootContainerElement.nodeType === DOCUMENT_NODE
            ? (rootContainerElement: any)
            : rootContainerElement.ownerDocument;
        }
        
  • HostText 相比于 HostComponents 来说,它没有多种选择

  • 没有各种各样的属性,整体来说非常的简单

  • 一些特别说明的,写在了上述代码注释中


http://www.niftyadmin.cn/n/5342821.html

相关文章

SQL Server多数据表之间的数据查询和分组查询

文章目录 一、多数据表之间的数据查询1.1内连接查询(Inner join)1.2 左外连接 (LEFT JOIN):1.3右外连接 (RIGHT JOIN):1.4. 全外连接 (FULL OUTER JOIN):1.5 交叉连接 (CROSS JOIN):1.6 自连接 (SELF JOIN):1.7 子查询: 二、分组查询2.1 分组查询2.2 查询…

leetcode670最大交换

给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。 示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。 注意: 给定数字的范围是 [0, 108] int maximumSwap(int num) {…

如何在Linux上部署Docker容器

一、什么是docker? Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不…

Harmony 鸿蒙驱动开发

驱动开发 驱动模型介绍 HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个Host(设备容器&#…

MySQL之数据库DDL

文章目录 MySQL数据库基本操作数据定义DDL对数据库的常用操作创建表修改表格式结构 MySQL数据库基本操作 首先我们先了解SQL的语言组成,他分为四个部分 数据定义语言(DDL)数据操纵语言(DML)数据控制语言(…

算法训练营Day45(动态规划7)

70. 爬楼梯 (进阶) 卡码网:57. 爬楼梯 提醒 这道题目 爬楼梯之前做过,这次再用完全背包的思路来分析一遍 322. 零钱兑换 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 提醒 如果求组合数就是外层for…

在VBA中使用SQL

VBA在处理大量的数据/计算时如果使用常规方法会比较慢,因此需要对其进行性能优化以提高运行速度,一般的方法是数组计算或者sql计算。SQL计算的速度最快,限制也是最多的,数组速度其次,灵活性也更高 如果要在vba中调用sql处理数据基本可以遵循一个套路,只要修改其中的SQL语…

红队视角下的公有云基础组件安全(二)

前言 我们已经发过一篇红队视角下的公有云基础组件安全的文章,这篇是对上一篇内容的补充,主要为国外公有云如AWS、Google Cloud、Azure。 本文主要从红队视角讲述公有云基本服务中一些因配置问题产生的安全风险。 目录 ● 云存储 ● 云计算 ● 云网…