portal 将子元素渲染到 DOM 中的不同位置(在父元素 DOM 层次结构之外),同时将它们保留在 React 的组件树中——因此上下文、props 和事件仍然像正常嵌套一样工作。
jsx
{ createPortal } ;
() {
(
,
.()
);
}
模态框、工具提示、下拉菜单和 toast 必须逃脱祖先的 overflow: hidden 或 z-index 堆叠上下文。如果模态框嵌套在具有 overflow: hidden 的卡片内,它会被剪裁。通过 portal 渲染到 body 可以完全避免这种情况。
这是微妙而强大的部分:即使模态框的 DOM 存在于 body 下,React 祖先上的 onClick 仍然会触发,因为事件冒泡遵循 React 树,而不是 DOM 树:
<div onClick={handleParentClick}> {/* still fires for clicks inside the portal */}
<Modal>...</Modal>
</div>
Portal 解决了定位,而不是可访问性。对于对话框,您仍然需要焦点陷阱、role="dialog"/aria-modal 和按 Escape 关闭(或使用原生 <dialog> 元素来处理大部分工作)。