弹窗的主体设计没什么特别,就是把细分化后的各个功能封装在一个个的小组件内,然后再整合。这样逻辑就分开了,不乱。
弹窗容器
这个容器是弹窗主体的根组件(不含遮罩),要能根据主题的变化能做出相应的改变。还要记录渲染后的主体的大小参数,原为有最大化和最小化的操作,这些操作是依据当前主体的大小而计算得来的。
_ModelContianer.jsx
/** @jsxImportSource @emotion/react */
import {
css } from '@emotion/react'
import {
useRef, useState } from 'react';
import {
Paper } from '@mui/material';
import {
useModelState } from './_useModel';
import {
infoLevel } from './_ModelConfigure';
// 计算不同状态下的高度
const calHeight = (sizeMode, normalHeight) => {
switch (sizeMode) {
case 0:
return '45px';
case 1:
return normalHeight > 0 ? normalHeight + 'px' : 'auto';
case 2:
return '100vh';
default:
return 'auto';
}
}
// 最大化时的固定样式
const maxSizeCss = css`
width: 100vw;
height: 100vh;
top: 0;
left: 0;
`;
/**
* 弹窗容器
* @param {*} param0
* @returns
*/
const ModelContainer = ({
children }) => {
const modelState = useModelState();
const {
stateMode, // 弹窗的状态,0: 最小化, 1: 正常, 2: 最大化
level, // 弹窗的类型(主要是颜色类型),选项有:default, error, warning, success, info
isDark, //是否是暗黑模式
} = modelState;
const [nomalSize, setNormalSize] = useState({
width: 0, height: 0 });
const containerRef = useRef(null);
return (
<Paper
ref={
containerRef}
css={
css`
border: 1px solid #A0A0A0;
border-radius: 5px;
width: ${
stateMode === 2 ? '100vw' : stateMode === 0 ? '300px' : '576px' };
height: ${
calHeight(stateMode, nomalSize.height) };
overflow: hidden;
max-width: 100%;
max-height: 100vh;
display: flex;
flex-direction: column;
background-color: ${
isDark ? '#333' : infoLevel[level] ? infoLevel[level].color : "white" };
${
stateMode === 2 ? maxSizeCss : null};
tran