使用 Portals 构建模态框组件
创建可复用的模态框,通过 createPortal 渲染到 document.body。
使用 Portals 构建模态框组件 是 CoddyKit 上的免费 React Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
欢迎
在本课中,您将构建一个可复用的 Modal 组件。它使用 React.createPortal 将内容渲染到 document.body 中,并支持点击背景和按 Escape 键关闭。
模态框组件骨架
先从基本结构开始:创建一个接受 `isOpen`、`onClose` 和 `children` 属性的 Modal 组件。当 `isOpen` 为 false 时,不渲染任何内容。
function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;
return createPortal(
<div className="backdrop" onClick={onClose}>
<div className="modal" onClick={e => e.stopPropagation()}>
{children}
</div>
</div>,
document.body
);
}背景与阻止冒泡
外层的 `backdrop` div 覆盖整个屏幕。点击它会调用 `onClose`。内部的 `modal` div 调用 `e.stopPropagation()`,这样模态框内部的点击就不会冒泡到背景,也不会意外将其关闭。
使用 Escape 键关闭
添加一个 `useEffect` 来监听 `keydown` 事件。当按下 Escape 键且模态框处于打开状态时,调用 `onClose`。清理时移除该监听器。
useEffect(() => {
if (!isOpen) return;
const handle = (e) => { if (e.key === 'Escape') onClose(); };
document.addEventListener('keydown', handle);
return () => document.removeEventListener('keydown', handle);
}, [isOpen, onClose]);阻止页面滚动
模态框打开时,通常需要阻止其后方页面滚动。请在 `useEffect` 中对 `document.body` 添加和移除 `overflow: hidden`。
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
}
return () => { document.body.style.overflow = ''; };
}, [isOpen]);模态框的基础 CSS
背景应是覆盖全屏的固定覆盖层。模态框应居中显示。最简单的 CSS 方式是在背景上使用 flexbox 来使模态框居中。
.backdrop {
position: fixed; inset: 0;
background: rgba(0,0,0,0.5);
display: flex; align-items: center; justify-content: center;
z-index: 1000;
}
.modal {
background: white;
border-radius: 8px;
padding: 24px;
min-width: 320px;
}使用模态框
请在父组件中使用布尔状态来控制模态框。将 `isOpen` 和 `onClose` 属性传递给 Modal。将任意内容作为子元素放入其中。
function App() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Open Modal</button>
<Modal isOpen={open} onClose={() => setOpen(false)}>
<h2>Hello from the modal!</h2>
<button onClick={() => setOpen(false)}>Close</button>
</Modal>
</>
);
}在内部添加关闭按钮
请始终在模态框内部提供明确的关闭按钮,以便无法使用键盘或没有注意到背景的用户关闭它。通过子元素或属性将 `onClose` 传递给内容。
使用 CSS 过渡制作动画
要实现淡入效果,不要在关闭时返回 null,而是始终渲染门户并切换 CSS 类。请在背景上使用 CSS `opacity` 和 `transform` 过渡。
// Toggle class based on isOpen
<div className={`backdrop ${isOpen ? 'visible' : 'hidden'}`}>组合模态框页眉与页脚
将模态框拆分为子组件:`Modal.Header`、`Modal.Body`、`Modal.Footer`。使用复合组件模式,让使用者无需了解类名即可组合模态框布局。
快速检查
为什么要在内部模态框 div 的 onClick 处理程序中调用 e.stopPropagation()?
回顾
您已经使用 createPortal 构建了 Modal:点击背景会关闭它,Escape 键会关闭它,打开时会锁定页面滚动,而 stopPropagation 会防止模态框内部的点击将其关闭。
接下来
下一课:**处理模态框中的焦点与键盘陷阱**——您将让焦点在模态框打开期间保持在其内部,以满足可访问性要求。
常见问题解答
「使用 Portals 构建模态框组件」课时是免费的吗?
是的 — 「使用 Portals 构建模态框组件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「使用 Portals 构建模态框组件」这节课中我会学到什么?
创建可复用的模态框,通过 createPortal 渲染到 document.body。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 Portals 构建模态框组件」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 什么是 React Portals?
- 使用 Portals 构建模态框组件
- 处理模态框中的焦点与键盘陷阱
- 使用 Portals 构建工具提示与下拉菜单