React16源码: React中的PortalComponent创建, 调和, 更新的源码实现

HyperLedger Fabric实战(一):基础环境构建 简介 本文将介绍从一台裸机上面如何构建出一个可用的Fabric网络(单机版,非测试网络)。 基础环境构建 Fabric组件安装 阅读详情

PortalComponent


1 )概述

  • React Portal之所以叫Portal,因为做的就是和“传送门”一样的事情
  • render到一个组件里面去,实际改变的是网页上另一处的DOM结构
  • 主要关注 portal的创建, 调和, 更新过程

2 )源码

定位到 packages/react-dom/src/client/ReactDOM.js#L576

function createPortal(
  children: ReactNodeList,
  container: DOMContainer,
  key: ?string = null,
) {
  invariant(
    isValidContainer(container),
    'Target container is not a DOM element.',
  );
  // TODO: pass ReactDOM portal implementation as third argument
  return ReactPortal.createPortal(children, container, null, key);
}

  • 这里调用的是 ReactPortal.createPortal, 进入

    // packages/shared/ReactPortal.js#L14
    export function createPortal(
      children: ReactNodeList,
      containerInfo: any,
      // TODO: figure out the API for cross-renderer implementation.
      implementation: any,
      key: ?string = null,
    ): ReactPortal {
      return {
        // This tag allow us to uniquely identify this as a React Portal
        $$typeof: REACT_PORTAL_TYPE,
        key: key == null ? null : '' + key,
        children,
        containerInfo, // dom 挂载节点
        implementation,
      };
    }
    
    • 这里返回一个对象,类似于 ReactElement
    • 区别在于 $$typeof 和 containerInfo 需要的挂载点
  • 对于 REACT_PORTAL_TYPE 类型的组件在 reconcile 时, 看下具体操作, 找到 reconcileSinglePortal

    // packages/react-reconciler/src/ReactChildFiber.js#L1171
    function reconcileSinglePortal(
      returnFiber: Fiber,
      currentFirstChild: Fiber | null,
      portal: ReactPortal,
      expirationTime: ExpirationTime,
    ): Fiber {
      const key = portal.key; // 当前的 key
      let child = currentFirstChild;
      // 如果 存在 child, 对比 child.key === key
      while (child !== null) {
        // TODO: If key === null and child.key === null, then this only applies to
        // the first item in the list.
        if (child.key === key) {
          // 关注这里,有 containerInfo 的对比,portal 需要关心渲染到的节点是否有变化
          // 如果节点有变化,那么这个 portal 的渲染过程也会有变化
          // 都符合,说明老节点都可以复用
          if (
            child.tag === HostPortal &&
            child.stateNode.containerInfo === portal.containerInfo &&
            child.stateNode.implementation === portal.implementation
          ) {
            deleteRemainingChildren(returnFiber, child.sibling); // 删除其他节点
            // 通过 useFiber 复用这个节点
            const existing = useFiber(
              child,
              portal.children || [],
              expirationTime,
            );
            existing.return = returnFiber;
            return existing;
          } else {
            // key相同,但是不符合上述if, 没法复用,删除干净
            deleteRemainingChildren(returnFiber, child);
            break;
          }
        } else {
          // key 不同,删除当前节点
          deleteChild(returnFiber, child);
        }
        child = child.sibling;
      }
    
      // 创建一个 portal 的 fiber 对象
      const created = createFiberFromPortal(
        portal,
        returnFiber.mode,
        expirationTime,
      );
      created.return = returnFiber;
      return created;
    }
    
  • 对于更新一个portal节点,进入 updatePortalComponent

    // packages/react-reconciler/src/ReactFiberBeginWork.js#L1322
    function updatePortalComponent(
      current: Fiber | null,
      workInProgress: Fiber,
      renderExpirationTime: ExpirationTime,
    ) {
      // 挂载点处理
      pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
      const nextChildren = workInProgress.pendingProps; // 这里 pendingProps 是 children
      if (current === null) {
        // Portals are special because we don't append the children during mount
        // but at commit. Therefore we need to track insertions which the normal
        // flow doesn't do during mount. This doesn't happen at the root because
        // the root always starts with a "current" with a null child.
        // TODO: Consider unifying this with how the root works.
        workInProgress.child = reconcileChildFibers(
          workInProgress,
          null,
          nextChildren,
          renderExpirationTime,
        );
      } else {
        reconcileChildren(
          current,
          workInProgress,
          nextChildren,
          renderExpirationTime,
        );
      }
      return workInProgress.child;
    }
    
    • 之前梳理过的 API 不再赘述
    • 一些API的调用,在源码的注释中
GB28181 —— 1、Ubuntu20.04下使用ZLMediaKit+WVP搭建GB28181流媒体监控平台(连接带云台摄像机) GB28181 —— Ubuntu20.04下使用ZLMediaKit+WVP搭建GB28181流媒体监控平台 阅读详情

相关推荐

Jupyter实战:解决ModuleNotFoundError之xgboost缺失问题

本文详细解析了在Jupyter Notebook中遇到ModuleNotFoundError: No module named 'xgboost'错误的完整解决方案。通过诊断环境、使用pip正确安装xgboost、配置Python路径以及最终验证,帮助用户彻底解决模块缺失问题,并理解Jupyter内核与Python环境的关系,提升问题排查能力。

weixin_29064103的博客 384

React.16 Portals使用案例

React.16 Portals使用案例介绍案例 介绍 React 16的Portals特性让我们可以把组件渲染到当前组件树以外的DOM节点上,这个特性典型的应用场景是渲染应用的弹窗,使用Portals后,任意组件都可以将弹窗组件渲染到根节点上,以便弹窗的显示,Portals的实现依赖ReactDOM的一个新的API。 案例 说了这么多,可能还是不大明白怎么用,或者什么场景要用,通过下面这个小实例...

weixin_43443341的博客 371

Intel Realsense windows安装与入门

realsense400系列介绍: https://www.intelrealsense.com/stereo-depth/?utm_source=intelcom_website&utm_medium=button&utm_campaign=day-to-day&utm_content=D400_learn-more_button realsense 435i介绍: ...

hanshuning的专栏 1万+

React16 新特性总结

createPortal createPortal 的出现为 弹窗、对话框 等脱离文档流的组件开发提供了便利,Portals 提供了一种很好的将子节点渲染到父组件以外的 DOM 节点的方式。 const modalRoot = document.body; class Modal extends React.Component { constructor(props) { ...

99的博客 618

逆向实战:手把手教你分析Google DroidGuard虚拟机的加密与反调试(附Python脚本)

本文深入解析Google DroidGuard虚拟机的加密机制与反调试策略,提供从环境配置到逆向分析的完整实战指南。通过IDA Pro、Frida等工具链,详细剖析DroidGuard的信号拦截、内存校验等保护机制,并附Python脚本实现自动化分析,助力Android安全研究人员突破GMS核心组件的安全防护。

weixin_32428571的博客 313

告别系统迁移蓝屏!用Intel RST驱动搞定11代酷睿装Win11的硬盘识别难题

本文详细介绍了如何通过Intel RST驱动解决11代酷睿处理器在安装Win11时遇到的硬盘识别问题。针对VMD技术导致的系统迁移蓝屏错误,提供了从驱动下载、PE环境创建到驱动注入的完整解决方案,帮助用户顺利完成系统升级或迁移。

weixin_31309419的博客 579

React 16新特性简介

React 16新特性简介 1.render支持Array和String渲染 render() { return [ <li key="A">First item</li>, <li key="B">Second item</li>, <li key="C">Third item</li>, ...

qq_36742720的博客 709

手把手教你学veriolg(二十六)-- Verilog CIC 滤波器设计

目录 Verilog CIC 滤波器设计1. CIC 滤波器的基本原理2. Verilog 实现3. 说明4. 测试激励5. 总结 CIC(Cascade-Integrator-Comb)滤波器是一种特殊的数字滤波器,常用于多速率信号处理中,尤其是用于信号的上采样(插值)和下采样(抽取)。CIC 滤波器的特点在于它具有简单的硬件实现、不需要乘法器(仅使用加法器和延迟元件)、且具有线性相位特性。然而,CIC 滤波器的缺点是它会产生较大的量化误差,因此在设计时需要特别注意字长的选择以避免溢出。1. CIC 滤波

MHD0815的博客 891

React16新特性

       React16是Facebook在2017年9月发布的React最新版本。他是基于代号为“Fiber”的新架构实现,几乎对React的底层代码进行了重写,但是原本对外的api保持不变,所以基本可以无缝的迁移到React16,但是对于React16基于以前版本的React实现了许多比较新的特性。       一,React的render方法返回的新类型:支持两种类型数组(由React元...

蜗牛不会跑 2587

疾风气象大模型4.0白皮书

《疾风气象大模型白皮书摘要》 疾风气象大模型(J-AFM)是国内首个基于3D建模的气象智能平台,突破传统二维气象分析的局限,采用体素化技术构建"x-y-z-t"四维统一模型,实现从分钟级短临到30天跨时效的连续预测。核心技术包括:1)多源数据三维同化,融合雷达、卫星、风廓线等异构数据;2)物理约束AI解码器,嵌入能量守恒、湍流封闭等气象原理;3)行业适配插件,服务风电、光伏、航空等领域,如山地风场尾流校正、云影短临预测。平台支持批流一体推理与边缘部署,提供概率化输出和误差溯源能力,显著降

专注AI大模型,软件混淆,授权 545

YOLOv13添加DRB模块map暴涨12.33!准确率提升8.56!召回率提升15.66

本文介绍了在YOLOv13模型中添加DRB模块的改进方法。实验结果显示,添加DRB模块后模型性能显著提升,mAP暴涨12.33%,准确率提升8.56%。文章详细说明了移植过程,包括创建yolov13-DRB.yaml配置文件、修改tasks.py和__init__.py文件,以及引入UniRepLKNet模块的具体实现。其中重点描述了GRNwithNHWC、NCHWtoNHWC等核心组件的实现细节,并提供了完整的模型结构配置代码。这些改进使得YOLOv13模型在保持原有架构优势的同时,获得了更强大的特征提取

FJN110的博客 2822

React16—— Portals

背景介绍 想象一下现在有图1所示的组件结构,并且D组件是相对于A组件定位的。通常有两种解决方式: ...

qq_23921097的博客 377

24、中性原子量子计算:原理、方法与实验

本文系统介绍了中性原子量子计算的原理、方法与实验进展。重点阐述了利用碱金属原子作为量子比特,通过磁光阱、光偶极阱和光晶格等技术实现原子捕获与控制的方法。同时,详细分析了单量子比特门操作和量子态工程的实现手段,并总结了相关实验结果与未来发展方向。该技术路线为构建大规模量子计算系统提供了可行方案。

ol789012的博客 248

React16 新特性

1 引言 于 2017.09.26 Facebook 发布 React v16.0 版本,时至今日已更新到 React v16.6,且引入了大量的令人振奋的新特性,本文章将带领大家根据 React 更新的时间脉络了解 React16 的新特性。 2 概述 按照 React16 的更新时间,从 React v16.0 ~ React v16.6 进行概述。 React v16.0 render 支...

weixin_34321753的博客 378

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

React.createPortal 及 Modal 的新实现方式

一、描述 二、之前的 Modal 组件 三、 createProtal 改造 Modal 组件: 1、html 预留容器 2、改造 Modal 容器 3、Modal 组件的内容 4、使用 Modal 容器组件和内容组件 5、效果 一、描述 一般使用 React 的组件都是挂到父组件的this.props.children上面,总是被最近的父组件所捕获,最终到 ...

飞翔的熊blabla 9405

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

react16中ref的使用

在 React16 新版本中,新引入了 React.createRef 与 React.forwardRef 两个 API,有计划移除老的 string ref,使 ref 的使用更加便捷与明确。如果你的应用已经升级到 React16.3+ 版本,那就放心大胆使用 React.createRef 吧,如果暂时没有的话,建议使用 callback ref 来代替 string ref。 strin...

马优晨 6907

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

React 16.0中的新特性——portal及其注意点

简要介绍:React16.0中发布了很多新特性,我们来看portal,React提供了一个顶级API—portal,用来将子节点渲染到父节点之外的dom节点 1.基本用法 (1)在React15.X版本中,我们只能讲子节点在父节点中渲染,基本用法如下: render() { // React需要创建一个新的div来包含子节点 return ( &lt;div&gt; ...

liwusen的博客 6309

react 16

react 16

kk的笨脑壳 682

Fix signatures do not match the previously installed version

报错信息FAILURE: Build failed with an exception.* What went wrong: Execution failed for task ':app:installDebug'. > com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: Fai

Wang的专栏 2万+

在react中 实现 base64的图片转换成formdata格式并实现上传功能

如果不想要服务端实现处理base64格式的图片的转换,那么在浏览器端来实现,部分属于伪代码,仅作为开发参考,请勿直接拷贝使用

Wang的专栏 8836

快速解决gradle下载慢的问题的小技巧

在ionic run 或build 或clean命令的时候,如果没有下载过gradle, 需要重新下载一次,而通过CLI的方式下载很慢,即使科学上网后,下载还是存在一些问题。这里总结一下,快速的下载安装方式。 步骤 本地安装 http-server 包, 通过 $ npm i -g http-server 的方式安装到全局 在官网上下载自己的版本,目前自带的版本是 2.14.1,其他版本可能在执行过

Wang的专栏 6714

React 实现 2D 画板功能

在移动端或者PC端我们来模拟画板的实现, 支持清除和导出功能,此处简单实现,仅作开发参考。 效果演示 主要代码演示 /* 此模块用于实现签名绘图功能 */ // 需要用到的变量定义 let clickX = new Array(); let clickY = new Array(); let clickDrag = new Array(); let paint; let point...

Wang的专栏 4325

React16源码: React中LegacyContext的源码实现

对于在 beginWork 中的 context 操作,可以看上述判断成立的条件下的代码,即便有符合跳过更新的操作,依然 需要 push 和 pop 操作。如果我们可以跳出组件的更新,也就是代表着当前这个 classComponent,它的state它的props都应该是没有任何变化的。对于子组件来说,它的所有子树所获取到的context肯定是经过子组件,和上层的父组件合并的 context 了, 也就是。所以,先 push 一个老的值进去再说, 然后到后面,如果发现这个组件它是要更新的,就调用这个。

Wang的专栏 2803

Fix babel-preset-react-native TransformError

错误环境新版本存在不兼容,在运行 react-native run-android 的时候,发生的错误分析: babel-preset-react-native version : @3.0.0 $ react-native -v :react-native-cli: 2.0.1 react-native: 0.47.1$node -v : v7.8.0 $ npm -v :4.4.4 解决方案

Wang的专栏 2800

React18原理: 再聊Fiber架构下的时间分片

react的任务可以被打断,其实就是基于时间分片的,人眼最高能识别的帧数不超过30帧,电影的帧数差不多是在24,浏览器的帧率一般来说是60帧,也就是每秒60个画面, 平均一个画面大概是16.5毫秒左右,浏览器正常的工作流程是运算渲染,运算,渲染运算渲染,在浏览器里面一个运算,加上一个渲染就是一帧

Wang的专栏 2796

在react项目中修改webpack中本地服务器架设的目录

一个产品的上线往往会有很多的问题,现在就出现一个需求,我们是在服务器下的某个目录进行发布,而不是根服务器,服务端不想为一个项目配置ip地址,而在react项目中,默认是走的根路径,现在我们就开始修改一下它。 前提说明 如果我们需要修改手动配置webpack, 那么根据现在的版本, 我们只能执行 npm run eject, 之后就可以着手修改了。 webpack中与需求相关的...

Wang的专栏 2397
上一篇: React16源码: React中的HostComponent & HostText的源码实现
下一篇: React16源码: React中的updateMode的源码实现
Wang's Blog
博客等级 码龄12年 7438粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值