封装react弹窗组件并且挂载到body节点
import React, { ReactElement, useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import styled from './index.less';
export type Iprops = {
open: boolean;
onCancel: () => void;
children: ReactElement;
width: string;
};
const Dialog: React.FC<Partial<Iprops>> = (props: any) => {
const [visibleShow, setVisibleShow] = useState<boolean>(false);
const { width = '50%' } = props;
useEffect(() => {
setVisibleShow(props.open);
}, [props.open]);
return ReactDOM.createPortal(
<>
{visibleShow ? (
<div key={Math.random() * 100} className={styled.dialogWrapper}>
<div className={styled.content}>
<div style={{ width: width }} className={styled.dialogContent}>
<div className={styled.header}>
<div
onClick={() => {
props.onCancel();
}}
>
关闭
</div>
</div>
{props.children}
</div>
</div>
</div>
) : null}
</>,
document.body,
);
};
export default Dialog;
.dialogWrapper {
position: fixed;
top: 0;
right: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
animation: animationOpcity 0.5s ease-in-out;
}
.content {
position: relative;
width: 100%;
height: 100%;
.dialogContent {
position: absolute;
top: 20%;
left: 50%;
min-height: 200px;
background: #ffffff;
transform: translate(-50%, 0%);
animation: animationName 0.5s ease-in;
.header {
width: 100%;
height: 62px;
background: red;
}
}
}
@keyframes animationName {
0% {
opacity: 0;
}
percentage {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
@keyframes animationOpcity {
0% {
opacity: 0;
}
percentage {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
一个简单的组件封装就完成了可以在这个基础上继续拓展更复杂的功能,比如支持react.reactNode节点等等功能。