当前位置: 首页 > news >正文

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

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 argumentreturn 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
    • 区别在于 $$typeofcontainerInfo 需要的挂载点
  • 对于 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; // 当前的 keylet child = currentFirstChild;// 如果 存在 child, 对比 child.key === keywhile (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 是 childrenif (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的调用,在源码的注释中

相关文章:

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

PortalComponent 1 )概述 React Portal之所以叫Portal,因为做的就是和“传送门”一样的事情render到一个组件里面去,实际改变的是网页上另一处的DOM结构主要关注 portal的创建, 调和, 更新过程 2 )源码 定位到 packages/react-…...

Hive-SQL语法大全

Hive SQL 语法大全 基于语法描述说明 CREATE DATABASE [IF NOT EXISTS] db_name [LOCATION] path; SELECT expr, ... FROM tbl ORDER BY col_name [ASC | DESC] (A | B | C)如上语法,在语法描述中出现: [],表示可选,如上[LOCATI…...

编译原理2.3习题 语法制导分析[C++]

图源:文心一言 编译原理习题整理~🥝🥝 作为初学者的我,这些习题主要用于自我巩固。由于是自学,答案难免有误,非常欢迎各位小伙伴指正与讨论!👏💡 第1版:自…...

JUC-CAS

1. CAS概述 CAS(Compare ans swap/set) 比较并交换,实现并发的一种底层技术。它将预期的值和内存中的值比较,如果相同,就更新内存中的值。如果不匹配,一直重试(自旋)。Java.util.concurrent.atomic包下的原…...

Effective C++——关于重载赋值运算

令operator返回一个*this的引用 在重载,,*等运算符时&#xff0c;令其返回一个指向this的引用。 class MyClass {int* val; public:MyClass(int i) : val(new int(i)){}MyClass():val(new int(0)){}void print() {cout << *val << endl;}MyClass& operator(co…...

vscode debug

需要对GitHub上的工程debug。 所以花时间看了下,参考了bili视频和chatgpt的解答。 chatgpt给的步骤 要在 VS Code 中调试 C++ 项目,可以按照以下步骤进行设置和操作: 确保已安装 C++ 扩展:在 VS Code 中选择 “Extensions”(或使用快捷键 Ctrl+Shift+X),搜索并安装官…...

数据库选型其实技术维度不太重要

看到这个标题可能觉得我在乱说&#xff0c;数据库选型要从多个角度和维度看来&#xff0c;还有各种POC。很多供应商朋友告诉我POC是一个漫长的过程&#xff0c;非常痛苦&#xff0c;要解决各种技术问题。怎么能说和技术无关呢&#xff1f; 因为从我的经历和周围听说的经验来说…...

【C++】入门(二)

前言&#xff1a; c基础语法&#xff08;下&#xff09; 文章目录 五、引用5.1 引用概念5.2 引用使用规则5.3 常引用5.4 引用的使用场景5.5 引用和指针的区别 六、内联函数6.1 概念6.2 内联函数的特性 七、auto关键字&#xff08;C11&#xff09;7.1 概念7.2 使用规则7.3 用于f…...

Nginx 代理服务路径带/和不带/的问题

nginx初始配置如下 server {listen 6087;location / {#网站主页路径。此路径仅供参考&#xff0c;具体请您按照实际目录操作。#例如&#xff0c;您的网站运行目录在/etc/www下&#xff0c;则填写/etc/www。#允许跨域请求的域&#xff0c;* 代表所有add_header Access-Control-…...

C# CefSharp 输入内容,点击按钮,并且滑动。

前言 帮别人敲了个Demo,抱试一试心态&#xff0c;居然成功了&#xff0c;可以用。给小伙伴们看看效果。 遇到问题 1&#xff0c;input输入value失败&#xff0c;里面要套了个事件&#xff0c;再变换输入value。后来用浏览器开发工具&#xff0c;研究js代码&#xff0c;太难了&a…...

历经15年,比特币以强势姿态进军华尔街!270亿美元投资狂潮引发市场震荡!

本月&#xff0c;比特币庆祝了它的15岁生日&#xff0c;并以强势的姿态进军华尔街。最近美国交易所开始交易的比特币交易所交易基金&#xff08;ETF&#xff09;&#xff0c;已经获得了投资者的广泛接受。这一进展标志着比特币作为一种年轻资产迈向成熟的重要里程碑。 根据Glas…...

GBASE南大通用的接口程序GBase ADO.NET

GBase ADO.NET 是一个提供.NET 应用程序与 GBase 数据库之间方便、高效、 安全交互的接口程序&#xff0c;使用 100%纯 C#编写&#xff0c;并继承了 Microsoft ADO.NET 类。 开发人员可以使用任何一种.NET 开发语言&#xff08;C#、VB.NET、F#&#xff09;通过 GBase ADO.NET 操…...

算法训练营Day57(回文子串--总结DP)

647. 回文子串 647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; class Solution {public int countSubstrings(String s) {int len s.length();//i到j这个子串是否是回文的boolean [][] dp new boolean[len][len];int res 0;for(int i len-1;i>0;i--){for(int …...

使用OpenCV从一个矩阵提取子矩阵

介绍opencv的两个函数&#xff1a;Range()和Rect() Range()是用于表示一个范围的类。它的构造函数有两个整数参数&#xff0c;分别表示范围的起始和终止索引。这个范围包括起始索引但不包括终止索引。 cv::Range(int start, int end); /* 在OpenCV中&#xff0c;cv::Range() …...

微信云托管:基本使用指南

微信云托管 &#x1f6a8;推荐&#xff1a;微信云托管&#xff1a;基本使用指南 确实是个好平台&#xff0c;部署个项目很简易&#xff0c;免去了很多运维上的事情。 一、微信云托管 github 流水线配置 和 端口号 首先&#xff0c;这里的主体(宿主机)&#xff0c;指的就是你的…...

WEB前端IDE的使用以及CSS的应用

IDE的使用 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…...

python中排序函数sorted的简单运用

# 假设a里面的()分别对应的x,y,w,h 即 (x,y,w,h) a [(2,3,1,2),(4,1,2,2),(1,6,2,1)] # a:传入的列表 # key 排序的数据 keylambda x:x[n] 是固定写法,里面的n代表你按照()中第几个数据的值排序 # eg&#xff1a;我们这里是x:x[0]表示我们按x排序, 如果改成x:x[1]则按y排序 # …...

k8s的helm

1、在没有helm之前&#xff0c;部署deployment、service、ingress等等 2、helm的作用&#xff1a;通过打包的方式&#xff0c;deployment、service、ingress这些打包在一块&#xff0c;一键部署服务、类似于yum功能 3、helm&#xff1a;官方提供的一种类似于仓库的功能&#…...

[MySQL]基础的增删改查

目录 1.前置介绍 2.数据库操作 2.1显示当前数据库 2.2创建数据库 2.3 使用数据库 2.4 删除数据库 3.常用数据类型 3.1整型和浮点型 3.2字符串类型 4.表的操作 4.1查看表结构 4.2创建表 4.3删除表 5.重点 5.1操作数据库 5.2常用数据类型 5.3操作表 1.前置介绍 …...

简易播放器 以及触发的异常

jl 1.0.jar 架包导入步骤&#xff1a; 1.读取到MP3音频文件 2.创建播放器对象,传入音频文件 3.开始播放 package com.ztt.Demo01;import java.io.FileInputStream; import java.io.FileNotFoundException;import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...