React Portals
什么是React Portals
React Portals(React 门户)是 React 提供的一种机制,用于将组件渲染到 DOM 树中的不同位置,而不受组件层次结构的限制。它允许你将一个组件的渲染内容“传送”到 DOM 结构中的任何位置,通常用于处理一些特殊的 UI 布局需求,如弹出窗口、模态框、通知框等。
React Portals 的主要优势是它可以在组件树中的某一级组件上渲染内容,而不受该组件的父组件或祖先组件的影响。这在处理全局或跨层级的 UI 元素时非常有用,因为它不会破坏组件的层次结构。
作用
React Portals 的主要作用是允许你将组件的渲染内容渲染到 DOM 结构中的不同位置,而不受组件层次结构的限制。它有几个重要的应用场景和作用:
-
处理全局 UI 元素: React Portals 允许你将 UI 元素渲染到应用的根 DOM 之外,这对于创建全局的 UI 元素非常有用,比如模态框、通知框、工具提示等。这些元素可以浮在应用的其他组件之上,而不会受到组件嵌套结构的影响。
-
处理层叠上下文: 有些 CSS 样式属性(如
z-index)会创建层叠上下文,限制了某些元素的显示顺序。使用 React Portals 可以将元素渲染到指定的 DOM 节点上,从而绕过这些层叠上下文的限制,实现更复杂的 UI 布局。 -
处理复杂的 UI 布局: 在某些情况下,需要将组件的渲染内容插入到 DOM 结构的特定位置,以满足设计或布局需求。React Portals 允许你在不改变组件层次结构的情况下实现这些需求。
-
提高可重用性: 使用 React Portals 可以将通用的 UI 组件(如模态框或通知框)封装为可重用的组件,使其可以在不同的应用中使用,并且不需要关心组件的放置位置。
原理
React Portals 的原理涉及到了 React 的虚拟 DOM以及底层的 DOM 操作。
-
创建虚拟 DOM 树: 在 React 组件中,你可以使用
ReactDOM.createPortal函数来创建一个 Portal。这个函数接受两个参数:要渲染的内容(通常是 React 元素)和目标 DOM 元素。 -
将虚拟 DOM 渲染到目标 DOM 元素: 当你调用
ReactDOM.createPortal时,React 会创建一个新的虚拟 DOM 子树,包括你传递的内容。然后,React 会使用底层的 DOM 操作,将这个虚拟 DOM 子树渲染到指定的目标 DOM 元素上,而不是按照通常的组件层次结构将其渲染到根 DOM 上。 -
维护 React 组件的状态: Portal 内部的 React 组件仍然保持其正常的生命周期和状态管理。这意味着你可以在 Portal 内部使用状态、事件处理程序等 React 功能。
-
脱离组件层次结构: Portal 允许你将内容渲染到组件树之外的位置,这意味着你可以创建全局的 UI 元素,如模态框、通知框等,而不受组件嵌套结构的限制。
-
卸载和更新: 当 Portal 所在的组件被卸载时,Portal 也会被卸载,并且 Portal 内的状态会被正确地清理。Portal 内容的更新也会被处理,React 会确保内容在目标 DOM 元素上得到正确渲染。
使用
使用 React Portals,需要使用 ReactDOM.createPortal 函数将组件的渲染内容渲染到指定的 DOM 元素上。以下是使用 React Portals 的一般步骤:
- 导入所需的模块: 首先,确保导入了
react和react-dom模块。
import React from 'react';
import ReactDOM from 'react-dom';
- 创建 Portal 组件: 创建一个 React 组件,这个组件将会用于包裹需要渲染的内容。通常,你可以在组件的
render方法中使用ReactDOM.createPortal函数来定义 Portal 的渲染内容以及目标 DOM 元素。
class MyPortal extends React.Component {constructor(props) {super(props);// 创建一个新的 DOM 元素用于 Portalthis.portalElement = document.createElement('div');// 定义要渲染到 Portal 上的内容this.portalContent = (<div><p>这是 Portal 中的内容</p></div>);}componentDidMount() {// 将 Portal 内容渲染到指定的 DOM 元素上document.body.appendChild(this.portalElement);this.componentDidUpdate();}componentDidUpdate() {// 使用 ReactDOM.createPortal 将内容渲染到 Portal 上ReactDOM.createPortal(this.portalContent, this.portalElement);}componentWillUnmount() {// 在组件卸载时,清理 Portaldocument.body.removeChild(this.portalElement);}render() {// 不需要在组件的 render 方法中返回任何内容return null;}
}
- 在应用中使用 Portal 组件: 在你的应用中,可以像使用普通的 React 组件一样使用 Portal 组件,并将其放置在组件树的合适位置。
function App() {return (<div><h1>我的应用</h1><MyPortal /></div>);
}ReactDOM.render(<App />, document.getElementById('root'));
在这个示例中,MyPortal 组件创建了一个 Portal,并将其内容渲染到了 document.body 中的新元素上。可以将 Portal 放置在任何组件中,不受组件层次结构的限制。
注意事项
在使用 React Portals 时,有一些注意事项和最佳实践需要考虑:
-
合适的目标容器: 确保选择一个合适的 DOM 元素作为 Portal 的目标容器。通常,你会在组件的
componentDidMount生命周期方法中将 Portal 添加到 DOM,而在componentWillUnmount中将其移除。 -
避免滥用: 虽然 React Portals 提供了灵活性,但不应滥用它们。只有在必要的情况下使用 Portal,避免过度复杂的嵌套结构。
-
层叠上下文: Portal 可能会破坏默认的 CSS 层叠上下文。如果你的 Portal 内容和其他元素有层叠关系,可能需要手动管理 z-index 或使用 CSS 属性来控制渲染顺序。
-
事件处理: 由于 Portal 的内容可以渲染在组件树之外,因此事件处理可能会受到限制。确保事件处理程序适用于 Portal 内容,或者使用事件冒泡机制。
假设有一个应用,其中包含一个按钮,当点击按钮时,应该显示一个模态框(使用 Portal 渲染)。组件可能如下所示:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';function Modal(props) {const { onClose } = props;return ReactDOM.createPortal(<div className="modal"><div className="modal-content"><p>这是模态框内容。</p><button onClick={onClose}>关闭</button></div></div>,document.getElementById('modal-root'));
}function App() {const [modalOpen, setModalOpen] = useState(false);const openModal = () => {setModalOpen(true);};const closeModal = () => {setModalOpen(false);};return (<div><h1>一个例子</h1><button onClick={openModal}>打开模态框</button>{modalOpen && <Modal onClose={closeModal} />}</div>);
}ReactDOM.render(<App />, document.getElementById('root'));
在上面的示例中,模态框的内容是使用 Portal 渲染的,而 Portal 的目标容器是具有 id="modal-root" 的 DOM 元素。
问题: 模态框中有一个 “关闭” 按钮,但当你点击它时,事件处理程序可能会受到限制,因为模态框渲染在组件树之外。
解决方法: 为了确保事件能够正确地触发和处理,你可以使用事件冒泡机制。在这个示例中,你可以在 “关闭” 按钮上添加事件处理程序,当点击按钮时,事件会冒泡到 DOM 树中,然后在组件树中的父组件中进行处理。
function Modal(props) {const { onClose } = props;return ReactDOM.createPortal(<div className="modal"><div className="modal-content"><p>这是模态框内容。</p><button onClick={onClose}>关闭</button></div></div>,document.getElementById('modal-root'));
}
在上述示例中,当点击模态框中的 “关闭” 按钮时,事件会冒泡回到包含模态框的组件(即 App 组件),然后在 App 组件中的 closeModal`处理函数中进行处理。
-
样式隔离: Portal 可能会引入样式隔离的问题。确保 Portal 内容的样式不会干扰到应用中的其他组件,可以使用 CSS Modules 或其他样式隔离方法。
-
性能考虑: Portal 可能会影响性能,因为它需要将内容渲染到不同的 DOM 元素上。在性能敏感的情况下,需要小心使用 Portal,确保不会导致性能问题。
-
跨浏览器兼容性: Portal 在不同浏览器上的行为可能有所不同。在使用 Portal 时,要测试和验证在各种主流浏览器中的表现。
相关文章:
React Portals
什么是React Portals React Portals(React 门户)是 React 提供的一种机制,用于将组件渲染到 DOM 树中的不同位置,而不受组件层次结构的限制。它允许你将一个组件的渲染内容“传送”到 DOM 结构中的任何位置,通常用于处…...
Python基础之高级函数
异常捕获 Python中,使用trycatch两个关键字来实现对异常的处理。在我们平时的工作中,异常的出现是在所难免的,但是异常一旦出现,极有可能会直接导致程序崩溃,无法正常运行,所以异常一定要及时的做出对应的…...
CSS3常用的新功能总结
CSS3常用的新功能包括圆角、阴渐变、2D变换、3D旋转、动画、viewpor和媒体查询。 圆角、阴影 border-redius 对一个元素实现圆角效果,是通过border-redius完成的。属性为两种方式: 一个属性值,表示设置所有四个角的半径为相同值ÿ…...
Lvs+KeepAlived高可用高性能负载均衡
目录 1.环境介绍 2.配置keepalived 3.测试 1.测试负载均衡 2.测试RS高可用 3.测试LVS高可用 3.1测试lvs主服务宕机 3.2.测试lvs主服务器恢复 4.我在实验中遇到的错误 1.环境介绍 环境:centos7 RS1---RIP1:192.168.163.145 VIP 192.168.163.200 RS2---RIP2…...
无涯教程-Android Online Test函数
Android在线测试模拟了真正的在线认证考试。您将看到基于 Android概念的多项选择题(MCQ),将为您提供四个options。您将为该问题选择最合适的答案,然后继续进行下一个问题,而不会浪费时间。完成完整的考试后,您将获得在线考试分数。 总问题数-20 最长时间-20分钟 Start Test …...
蓝桥杯打卡Day1
文章目录 全排列八皇后 一、全排列IO链接 本题思路:本题是一道经典的全排列问题,深度优先搜索即可解决。 #include <bits/stdc.h>constexpr int N10;std::string s; std::string ans; int n; bool st[N];void dfs(int u) {if(un){std::cout<<ans<…...
zipkin2.24.2源码install遇见的问题
1、idea导入项目后将Setting中的关于Maven和Java Compile相关的配置改为jdk11,同时Project Structure改为jdk11 2、将pom配置中的fork标签注释 标题未修改以上配置产生的问题 Compilation failure javac: Ч ı : --release : javac <options> <source files&g…...
yapi密码是如何生成的
yapi密码是如何生成的 关闭yapi注册功能后,想要通过手动插入用户数据到db中,那么密码是如何生成的呢? exports.generatePassword (password, passsalt) > { return sha1(password sha1(passsalt)); }; 所以如果想要创建一个用户&#x…...
2023-09-02 LeetCode每日一题(最多可以摧毁的敌人城堡数目)
2023-09-02每日一题 一、题目编号 2511. 最多可以摧毁的敌人城堡数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个长度为 n ,下标从 0 开始的整数数组 forts ,表示一些城堡。forts[i] 可以是 -1 ,0 或者 1 ,其中&…...
k8s环境部署配置
目录 一.虚拟机准备 二.基础环境配置(各个节点都做) 1.IP和hosts解析 2.防火墙和selinux 3.安装基本软件 4.配置时间同步 5.禁用swap分区 6.修改内核参数并重载 7.配置ipvs 三.docker环境(各个节点都做) 1.配置软件源并…...
Java之文件操作与IO
目录 一.认识文件 1.1文件是什么? 1.2文件的组织 1.3文件路径 1.4文件的分类 二.文件操作 2.1File概述 三.文件内容操作--IO 3.1JavaIO的认识 3.2Reader和Writer ⭐Reader类 ⭐Writer类 3.2FileInputStream和FileOutputStream ⭐FileInputStream类 …...
指令系统(408)
一、拓展操作码指令格式 【2017 统考】某计算机按字节编址,指令字长固定且只有两种指令格式,其中三地址指令29条、二地址指令107条,每个地址字段6位,则指令字长至少应该是( A) A、24位 B、26位 …...
Pygame中Trivia游戏解析6-3
3.3 Trivia类的show_question()函数 Trivia类的show_question()函数的作用是显示题目。主要包括显示题目框架、显示题目内容和显示题目选项等三部分。 3.3.1 显示题目的框架 在show_question()函数中,通过以下代码显示题目的框架。 print_text(font1, 210, 5, &q…...
热释电矢量传感器设计
1 概述 使用4个热释电传感器组成一个2X2的矩阵。通过曲线的相位差、 峰峰值等特征量来计算相关信息。本文使用STM32单片机设计、制作了热释电传感器矩阵;使用C#.NET设计了上位机软件。为以上研究做了试验平台。 2 硬件电路设计 2.1 热释电传感器介绍 热释电红外…...
MySql学习笔记10——视图介绍
视图 概述 view view可以看作是一张“虚拟表”,(但是他也是会作为文件存在的) 当我们通过复杂的查询语句获取一张表的时候,可以将这张表作为一个视图,和创建一个新表不同,在视图上进行的DML操作会对数据…...
【探索Linux】—— 强大的命令行工具 P.7(进程 · 进程的概念)
阅读导航 前言一、冯诺依曼体系结构二、操作系统(OS)1. 概念 三、进程1. 进程的概念2. PCB(Process Control Block)3. 查看进程 四、fork函数1. 函数简介2. 调用方式3. 返回值4. 使用示例 五、进程的几种状态1. 状态简介2. 进程状…...
JAVA宝典----容器(理解记忆)
目录 一、Java Collections框架是什么? 二、什么是迭代器? 三、Iterator与ListIterator有什么区别? 四、ArrayList、Vector和LinkedList有什么区别? 五、HashMap、Hashtable、TreeMap和WeakHashMap有哪些区别? 六…...
JS中的扩展操作符...(点点点)
标题 前言概述拓展操作符(Spread Operator)赋值与扩展操作符的区别 剩余操作符(Rest Operator) 前言 大家应该都在代码中用过或者看到…方法,我每次用到这个方法的时候都会想到第一次见到这个方法一头雾水的样子&#…...
找redis大key工具rdb_bigkeys
github官网 https://github.com/weiyanwei412/rdb_bigkeys 在centos下安装go [roothadoop102 rdb_bigkeys-master]# wget https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz [roothadoop102 rdb_bigkeys-master]# tar -zxf go1.13.5.linux-amd64.tar.gz -C /usr/local将g…...
ElasticSearch进阶
一、 search检索文档 ES支持两种基本方式检索; 通过REST request uri 发送搜索参数 (uri 检索参数);通过REST request body 来发送它们(uri请求体); 1、信息检索 API: https://w…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
