react 实现dialog组件
实现 React Dialog 组件的方法
使用 React 内置 API 创建基础 Dialog
通过 ReactDOM.createPortal 将 Dialog 渲染到 body 元素下,避免层级问题:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
const Dialog = ({ isOpen, onClose, children }) => {
if (!isOpen) return null;
return ReactDOM.createPortal(
<div className="dialog-overlay">
<div className="dialog-content">
{children}
<button onClick={onClose}>Close</button>
</div>
</div>,
document.body
);
};
// 使用示例
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(true)}>Open Dialog</button>
<Dialog isOpen={isOpen} onClose={() => setIsOpen(false)}>
<h2>Dialog Title</h2>
<p>This is dialog content</p>
</Dialog>
</div>
);
}
添加动画效果
使用 CSS transition 或第三方库(如 framer-motion)实现动画:
// 配合 CSS
.dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.dialog-overlay[data-state='open'] {
opacity: 1;
}
.dialog-content {
background: white;
padding: 20px;
border-radius: 4px;
transform: translateY(20px);
transition: transform 0.3s ease;
}
.dialog-overlay[data-state='open'] .dialog-content {
transform: translateY(0);
}
支持无障碍访问
添加 ARIA 属性和键盘事件处理:
const Dialog = ({ isOpen, onClose, children }) => {
useEffect(() => {
const handleKeyDown = (e) => {
if (e.key === 'Escape') onClose();
};
if (isOpen) {
document.addEventListener('keydown', handleKeyDown);
document.body.style.overflow = 'hidden';
}
return () => {
document.removeEventListener('keydown', handleKeyDown);
document.body.style.overflow = '';
};
}, [isOpen, onClose]);
if (!isOpen) return null;
return ReactDOM.createPortal(
<div
className="dialog-overlay"
onClick={onClose}
role="dialog"
aria-modal="true"
>
<div
className="dialog-content"
onClick={e => e.stopPropagation()}
>
{children}
<button onClick={onClose}>Close</button>
</div>
</div>,
document.body
);
};
使用第三方库快速实现
对于更复杂的需求,可以考虑使用现成的 Dialog 组件库:
// 使用 @radix-ui/react-dialog
import * as Dialog from '@radix-ui/react-dialog';
function RadixDialog() {
return (
<Dialog.Root>
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="dialog-overlay" />
<Dialog.Content className="dialog-content">
<Dialog.Title>Title</Dialog.Title>
<Dialog.Description>Description</Dialog.Description>
<Dialog.Close>Close</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}
样式定制化建议
通过 CSS 变量或 props 实现主题定制:
// 通过 props 控制样式
<Dialog
size="large"
theme="dark"
position="center"
/>
// 对应样式处理
.dialog-content[data-size='large'] {
width: 800px;
}
.dialog-content[data-theme='dark'] {
background: #333;
color: white;
}






