弹框组件的基本项目都会使用到,这次自定义实现一个简单的弹框组件。
显示标题,内容以及底部
主要用到的点:https://zh-hans.reactjs.org/docs/portals.html
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。
ReactDOM.createPortal(child, container)
第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。
代码如下
src\components\Dialog\index.jsx
文件
import React, { forwardRef, useEffect, useMemo, useState } from 'react'
import ReactDOM from 'react-dom';
import style from './index.css';
function Dialog(props) {
const { visible = false, title, children, footer } = props;
useEffect(() => {
// 查找dialog节点
let dom = document.getElementById('dialog');
// 存在即删除
(!visible && dom) && document.body.removeChild(dom);
// 设置属性id
let divDialog = document.createElement('div');
divDialog.setAttribute('id', 'dialog');
divDialog.setAttribute('class', 'dialog');
document.body.append(divDialog)
}, [])
return (
<>
{
(document.getElementById('dialog') && visible) && ReactDOM.createPortal(
<div className={style['H-Dialog-overview']}>
<div className={style['H-Dialog-inner']}>
<div className={style['dialog-header']}>
<h3>{title}</h3>
</div>
<div className={style['dialog-body']}>
{children}
</div>
<div className={style['dialog-footer']}>
{footer}
</div>
</div>
</div>, document.getElementById('dialog'))
}
</>
)
}
export default Dialog
src\components\Dialog\index.css
文件
.dialog {
}
.H-Dialog-overview {
/* 设置弹框背景以及无法点击页面*/
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1001;
background-color: rgba(0, 0,0,0.6);
display: flex;
justify-content: center;
}
.H-Dialog-inner {
height: 200px;
width: 400px;
background-color: #fff;
position: absolute;
top: 20vh;
padding: 20px;
}
.dialog-header {
margin-bottom: 10px;
}
.dialog-body{
}
.dialog-footer {
position: absolute;
bottom: 20px;
margin: auto;
text-align: center;
}
组件使用
src\pages\Home\index.jsx
文件
import { Button } from 'antd';
import React, { useState } from 'react';
import Dialog from '../../components/Dialog/index.jsx'
export default function Home() {
const [visible, setVisible] = useState(false)
return (
<div className="H-Home">
<h2>home</h2>
<h4>ui</h4>
<div>
<Button type='primary' onClick={() => {
setVisible(true)
}}>计算</Button>
</div>
<Dialog
visible={visible}
title={"这是一个弹窗"}
footer={
<>
<Button onClick={() => {
setVisible(false)
}}>确定</Button>
</>
}
>
<div>
hello
</div>
</Dialog>
</div>
)
}
效果图