React Portal 是一种优秀的方法,可以将子组件渲染到由组件树层次结构定义的父 DOM 层次结构之外的 DOM 节点中。Portal 的最常见用例是子组件需要从视觉上脱离父容器的情况,如下所示。
模态对话框
工具提示
悬浮卡片
加载器
可以使用 ReactDOM.createPortal(child, container)创建一个 Portal。这里的 child 是一个 React 元素、片段或字符串,而 container 是 Portal 应该注入到的 DOM 位置(节点)。
以下是使用上述 API 创建的一个示例模态(modal)组件。
const Modal =({ message, isOpen, onClose, children })=> { if (!isOpen) return null return ReactDOM.createPortal( <div className="modal"> <span className="message">{message}</span> <button onClick={onClose}>Close</button> </div>, domNode)}即使 Portal 是在父 DOM 元素外部渲染的,其行为也类似于应用程序中的常规 React 组件。它可以访问 props 和 context API。这是因为 Portal 位于 React Tree 层次结构内。想要看一看 React Portal 的实践示例,请查看在 Bit 的组件中心上分享的这个组件(你也可以使用 Bit 共享和重用组件):

示例:使用 React Portal 的 React 组件——在 Bit.dev 上分享
我们为什么需要它?
当我们在特定元素(父组件)中使用模态时,模态的高度和宽度将从模态所在的组件继承。因此,模态可能会被裁剪,而无法在应用程序中正确显示。传统上模态需要 CSS 属性,如 overflow:hidden 和 z-index,以避免出现这一问题。

被父组件覆盖高度和宽度的一个典型模态
上面的代码示例将导致在根下的嵌套组件内部渲染这个模态。使用浏览器检查这个应用程序时,它将显示元素,如下所示。

没有 React Portal 的模态渲染
让我们看看如何在这里使用 React Portal。以下代码将使用 createPortal(),在 root 树层次结构之外创建一个 DOM 节点来解决这个问题。
const Modal =({ message, isOpen, onClose, children })=> { if (!isOpen) return null; return ReactDOM.createPortal( <div className="modal"> <span>{message}</span> <button onClick={onClose}>Close</button> </div> ,document.body); }function Component() { const [open, setOpen] = useState(false) return ( <div className="component"> <button onClick={() => setOpen(true)}>Open Modal</button> <Modal message="Hello World!" isOpen={open} onClose={() => setOpen(false)} /> </div> )}下面显示的是一个 DOM 树层次结构,这是在使用 React Portal 时产生的,其中模态将被注入到 root 的外部,并与 root 处于同一级别。

使用 React Portal 渲染的模态
由于这个模态是在根层次结构之外渲染的,因此其尺寸不会被父组件继承或更改。

渲染为 Portal 的模型
你可以在这个 CodeSandbox 中找到这个示例,在其中可以试用代码、查看 Portal 的工作方式并解决所讨论的问题。
使用 Portal 时要注意的事项
使用 React Portal 时,你应该注意几个问题。下面提到的这些行为并不是直观可见的,你需要了解它们才行,因此我想在这里提一下。
事件冒泡(Event Bubbling)将照常工作:通过将事件传播到 React 树的祖先,事件冒泡将按预期工作,而与 DOM 中的 Portal 节点位置无关。
React 可以控制 Portal 节点及其生命周期:通过 Portal 渲染子元素时,React 仍然可以控制其生命周期。
Portal 仅影响 DOM 结构:Portal 仅影响 HTML DOM 结构,而不影响 React 组件树。
预定义 HTML 挂载点:使用 Portal 时,你需要定义一个 HTML DOM 元素作为 Portal 组件的挂载点。
小结
当我们需要在正常的 DOM 层次结构之外渲染子组件,而又不通过 React 组件树层次结构破坏事件传播的默认行为时,React Portal 就会派上用场。当渲染诸如模态、工具提示、弹出消息之类的组件时,它会很有用。
你可以在 React 官方文档中找到有关 Portal 的更多信息。
感谢阅读,请在下面的评论中分享你对这个主题的问题和评论,干杯!
原文链接:React Portals 简述及其用例





