本人已参与「新人创作礼」活动,一起开启掘金创作之路
弹出框,是我们前端在开发后台管理系统的常用组件,常见的功能如下:
| 参数 | 作用 |
|---|---|
| visible | 是否显示当前modal |
| onOk | 点击确定的回调 |
| onCancel | 点击取消的回调 |
| width | modal的宽度 |
| title | modal标题 |
| children | modal的内容 |
| mask | 是否展示遮罩 |
| maskClosable | 点击蒙层是否允许关闭 |
采用的技术栈:react,styled-components,TypeScript,可直接复制运行
import * as React from 'react'
import ReactDOM from 'react-dom'
import { useState,useEffect } from 'react';
import { MaskCss, ModalBody, ModalTitle, ModalContext, ModalBotton, Span, Img, ModalButtonOk, ModalButtonCancel } from './styled'
import { createRoot } from 'react-dom/client';
interface Props {
visible: boolean//是否显示当前modal
onOk?: () => void//点击确定的回调
onCancel?: () => void//点击取消的回调
width?: number//modal的宽度
title?: string//modal标题
children?: any//modal的内容
mask?: boolean//是否展示遮罩
maskClosable?: boolean//点击蒙层是否允许关闭
}
export const Modal = (props: Props) => {
const { visible, onOk, onCancel, width, title, children, mask, maskClosable } = props
const [time, setTime] = useState('0s')
const maskBoole = () => {
if (!maskClosable) return
onCancel!()
}
useEffect(() => {
setTime('0.3s')
}, [visible])
const modal = () => {
return ReactDOM.createPortal(<>
<MaskCss id='modal' style={{ 'backgroundColor': `rgba(0,0,0,${mask ? 0.1 : 0})` }} primary={visible} time={time} onClick={maskBoole}>
</MaskCss>
<ModalBody style={{ 'width': `${width ?? 600}px` }} primary={visible} time={time}>
<ModalTitle>
<Span>{visible ? title : ''}</Span>
<Img src={require('./sdao.png')} onClick={onCancel} />
</ModalTitle>
<ModalContext>
{visible ? children : ''}
</ModalContext>
<ModalBotton>
<ModalButtonOk onClick={onOk}>确定</ModalButtonOk>
<ModalButtonCancel onClick={onCancel}>取消</ModalButtonCancel>
</ModalBotton>
</ModalBody>
</>
, document.body)
}
return (
<>
{modal()}
</>
)
}
interface PropsShop {
onOk: () => void//点击确定的回调
onCancel: () => void//点击取消的回调
title: string//modal标题
children: any//modal的内容
}
let data: any = null
Modal.shop = (props: PropsShop) => {//静态调用
if (data) return
const modalbox = data = document.createElement('div')
document.body.appendChild(modalbox)
const ModalApp=()=>{
const [visible,setVisible]=useState<boolean>(true)
const onOk=()=>{
props.onOk()
setVisible(false)
}
const onCancel=()=>{
props.onCancel()
setVisible(false)
}
useEffect(()=>{
if(visible)return
document.body.removeChild(modalbox)
data = null
},[visible])
return <Modal {...props} visible={visible} onOk={onOk} onCancel={onCancel} />
}
const modalDom = createRoot(modalbox)
modalDom.render(<ModalApp/>)
}
css
import styled, { keyframes } from 'styled-components'
const dh=keyframes`
from{
opacity:0
}
to{
opacity:1
}
`
const hd = keyframes`
from{
opacity:1
}
to{
opacity:0
}
`
export const MaskCss = styled.div<{ primary?: boolean, time?: string }>`
position: fixed;
top:0;
height:100vh;
width:100vw;
z-index:${props => props.primary ? 1 : -2};
opacity:${props => props.primary ? 1 : 0};
animation:${props => props.primary ? dh : hd} ${props => props.time}
`
export const ModalBody = styled.div<{ primary?: Boolean, time?: string }>`
background-color: white;
border-radius: 5px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border:1px solid rgb(200,200,200);
z-index:${props => props.primary ? 3 : -3};
opacity:${props => props.primary ? 1 : 0};
animation:${props => props.primary ? dh : hd} ${props => props.time}
`
export const ModalTitle=styled.div`
padding:8px;
border-bottom:1px solid rgb(220,220,220);
display:flex;
justify-content: space-between;
align-items: center;
`
export const ModalContext=styled.div`
padding:10px;
min-height:300px;
border-bottom:1px solid rgb(220,220,220);
`
export const ModalBotton=styled.div`
padding:8px;
display:flex;
justify-content:end
`
export const Img=styled.img`
width:20px
`
export const ModalButtonOk=styled.button`
border:1px solid white;
border-radius:5px;
padding:6px 10px;
color:white;
background-color:#1296db;
margin-left:20px
`
export const ModalButtonCancel=styled(ModalButtonOk)`
background-color:white;
color:black;
border:1px solid rgb(200,200,200)
`
export const Span=styled.span`
font-size:18px
`
export const LabelBotton=styled(ModalButtonCancel)`
color:20px
border:1px solid black
`