Portals 传送门
让组件"跳出"父容器渲染
先说结论:Portal 让你的组件可以渲染到 DOM 树的任意位置,但依然保留 React 树中的父子关系。
什么场景用到它?
- 模态框 (Modal) — 需要盖住全屏,不受父级的
overflow: hidden 限制
- Tooltip / Popover — 悬浮卡片
- Toast 通知 — 弹窗提示
这些场景都需要"视觉上跳出当前容器"。
怎么用?
import ReactDOM from "react-dom";
function Modal({ children }) {
return ReactDOM.createPortal(
children,
document.body, // 渲染到 body 下
);
}
第一个参数是 JSX,第二个是目标 DOM 节点。
事件冒泡(容易理解错)
这是最坑的点:虽然渲染到了 body 下,但在 React 树里还是原来的父子关系。
// DOM 结构:Body -> Modal
// React 树:App -> Container -> Modal
function App() {
return (
<Container>
<Modal onClick={() => console.log("modal click")}>
<div>我是模态框</div>
</Modal>
</Container>
);
}
在 Modal 里点击,Container 的 onClick 也会触发!
因为 React 的合成事件是按 React 树走的,不是按 DOM 树。
总结
| 特点 | 说明 |
|---|
| 渲染位置 | 可以是任意 DOM 节点 |
| React 关系 | 保持不变 |
| 事件冒泡 | 按 React 树走 |
记住:Portal 就是"视觉上跑出去了,但 React 关系还在"。