5

React Portals 简述及其用例

 3 years ago
source link: https://www.infoq.cn/article/PP6MDaDeiGi6aKFmIhrg
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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 共享和重用组件):

3qmuUfF.gif!mobile

示例:使用 React Portal 的 React 组件——在 Bit.dev 上分享

我们为什么需要它?

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

IRZbey.png!mobile

被父组件覆盖高度和宽度的一个典型模态

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

JzM7Rna.jpg!mobile

没有 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 处于同一级别。

MfQfYvr.jpg!mobile

使用 React Portal 渲染的模态

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

jyQV7f.png!mobile

渲染为 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 简述及其用例


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK