React 实现弹窗/对话框有两种方案:
- 使用如Antd 等UI组件库:
(Antd 对话框的Modal,也是基于 React Portals特性实现的)
- 基于原生 React Portal
React Portal:
React 16.3 新引入的API,提供了一种将子节点渲染到存在于父组件以外的DOM节点的技术方案,解决了如:Dialog、Tooltip等悬浮层的问题。
例:实现自定义弹窗
1. index.html 中,创建一个 dialog 对话框容器
<div id="root"></div>
<div id="dialog-root"></div>
2. 实现弹窗组件
components/PortalDialog/index.jsx
import { createPortal } from 'react-dom';
import { Button } from 'antd';
import './style.css';
const PortalDialog = (props) => {
const { visible, children, onHide } = props;
return visible
? createPortal(
<div className="portal-custom">
{children}
<Button onClick={onHide}>close</Button>
</div>,
document.getElementById('dialog-root'),
)
: null;
};
export default PortalDialog;
components/PortalDialog/style.less
.portal-custom {
position: absolute;
padding: 20px;
width: 500px;
height: 300px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 10px;
border: 1px solid #ddd;
box-shadow: 0px 0px 20px 2px #ddd;
}
3. Dialog弹窗组件的使用
import React, { useState } from 'react';
import { Button } from 'antd';
import PortalDialog from '@/components/PortalDialog';
const DialogPage = () => {
const [isPortalVisible, setIsPortalVisible] = useState(false);
const showPortal = () => {
setIsPortalVisible(true);
};
const hidePortal = () => {
setIsPortalVisible(false);
};
return (
<>
<Button style={{ marginLeft: '20px' }} onClick={showPortal}>
Open Dialog(React Portals)
</Button>
<PortalDialog visible={isPortalVisible} onHide={hidePortal}>
<div>dialog-children</div>
</PortalDialog>
</>
);
};
export default DialogPage;