参考
createPortal(children, domNode, key?)
调用 createPortal
创建 portal,并传入 JSX 与实际渲染的目标 DOM 节点:
。
portal 只改变 DOM 节点的所处位置。在其他方面,渲染至 portal 的 JSX 的行为表现与作为 React 组件的子节点一致。该子节点可以访问由父节点树提供的 context 对象、事件将从子节点依循 React 树冒泡到父节点。
参数
children
:React 可以渲染的任何内容,如 JSX 片段(<div />
或<SomeComponent />
等等)、(<>...</>
)、字符串或数字,以及这些内容构成的数组。domNode
:某个已经存在的 DOM 节点,例如由document.getElementById()
返回的节点。在更新过程中传递不同的 DOM 节点将导致 portal 内容被重建。可选参数
key
:用作 portal 的独特字符串或数字。
返回值
createPortal
返回一个可以包含在 JSX 中或从 React 组件中返回的 React 节点。如果 React 在渲染输出中遇见它,它将把提供的 children
放入提供的 domNode
中。
警告
- portal 中的事件传播遵循 React 树而不是 DOM 树。例如点击
<div onClick>
内部的 portal,将触发onClick
处理程序。如果这会导致意外的问题,请在 portal 内部停止事件传播,或将 portal 移动到 React 树中的上层。
用法
渲染到 DOM 的不同部分
portal 允许组件将它们的某些子元素渲染到 DOM 中的不同位置。这使得组件的一部分可以“逃脱”它所在的容器。例如组件可以在页面其余部分上方或外部显示模态对话框和提示框。
调用 createPortal
并传入 JSX 与 应该放置的 DOM 节点 作为参数,然后渲染返回值以创建 portal:
React 将 传递的 JSX 对应的 DOM 节点放入 提供的 DOM 节点 中。
如果没有 portal,第二个 <p>
将放置在父级 <div>
中,但 portal 会将其“传送”到 中:
请注意,第二个段落在视觉上出现在带有边框的父级 <div>
之外。如果你使用开发者工具检查 DOM 结构,会发现第二个 <p>
直接放置在 <body>
中:
portal 只改变 DOM 节点的所处位置。在其他方面,portal 中的 JSX 将作为实际渲染它的 React 组件的子节点。该子节点可以访问由父节点树提供的 context 对象、事件将仍然从子节点冒泡到父节点树。
使用 portal 渲染模态对话框
你可以使用 portal 创建一个浮动在页面其余部分之上的模态对话框,即使呼出对话框的组件位于带有 overflow: hidden
或其他干扰对话框样式的容器中。
在此示例中,这两个容器具有破坏模态对话框的样式,但是渲染到 portal 中的容器不受影响,因为在 DOM 中,模态对话框不包含在父 JSX 元素内部。
将 React 组件渲染到非 React 服务器标记中
如果静态或服务端渲染的网站中只有某一部分使用 React,则 portal 可能非常有用。如果你的页面使用 Rails 等服务端框架构建,则可以在静态区域(例如侧边栏)中创建交互区域。与拥有 相比,portal 将应用程序视为一个单一的 React 树,即使它的部分在 DOM 的不同部分渲染,也可以共享状态。
将 React 组件渲染到非 React DOM 节点
你还可以使用 portal 来管理在 React 之外管理的 DOM 节点的内容。假设你正在集成非 React 地图小部件,并且想要在弹出窗口中渲染 React 内容,那么可以声明一个 popupContainer
state 变量来存储要渲染到的目标 DOM 节点:
在创建第三方小部件时,存储由小部件返回的 DOM 节点,以便可以将内容渲染到其中:
这样,一旦 popupContainer
可用,就可以使用 createPortal
将 React 内容渲染到其中:
以下是一个完整的示例,你可以尝试一下: