标准答案

  1. Portal 解决的是 DOM 挂载位置问题,让组件逻辑仍在原 React 树中,但 DOM 可以放到 body 或指定容器下。
  2. 弹窗、抽屉、Tooltip、Dropdown、Toast 常用 Portal 避免被父级 overflow、z-index、transform 等样式限制。
  3. Portal 不会改变 React 组件关系,context 仍然可以正常传递。
  4. React 合成事件会沿 React 组件树冒泡,即使真实 DOM 已经挂到另一个容器里。
  5. 使用 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 属性。

作者信息