标准答案
- Portal 解决的是 DOM 挂载位置问题,让组件逻辑仍在原 React 树中,但 DOM 可以放到 body 或指定容器下。
- 弹窗、抽屉、Tooltip、Dropdown、Toast 常用 Portal 避免被父级 overflow、z-index、transform 等样式限制。
- Portal 不会改变 React 组件关系,context 仍然可以正常传递。
- React 合成事件会沿 React 组件树冒泡,即使真实 DOM 已经挂到另一个容器里。
- 使用 Portal 时要额外处理焦点管理、滚动锁定、ESC 关闭、点击外部关闭和可访问性属性。
题目解析
这道题不能只说“挂到 body”。Portal 真正的价值是打破 DOM 层级限制,同时保持 React 组件关系。
事件冒泡是高频追问。真实 DOM 位置变了,但 React 的合成事件仍按照 React 树传递。
Portal 只是浮层基础设施,不自动解决弹窗交互细节。复杂组件还要处理焦点和可访问性。
代码示例
下面的 Modal 把内容渲染到 body 下,但组件仍由当前位置控制。
TSX
function Modal({ children }: { children: ReactNode }) {
return createPortal(
<div role="dialog" aria-modal="true">
{children}
</div>,
document.body
)
}常见误区
- 以为 Portal 会断开 context 或父子组件关系。
- 不知道 Portal 内合成事件仍会冒泡到 React 父组件。
- 只用 Portal 渲染弹窗,没有处理焦点、滚动锁定和 aria 属性。