React 模态框的设计(七)整合与测试

一个弹窗是不是也挺复杂的,是的,往往看似简单的东西真正做起来很复杂。只有多试验才能出真知。光看不练肯定是不行的。下面我们来把前几节的内容整合一下就大功告成了。

_Model.jsx

javascript 复制代码
/** @jsxImportSource @emotion/react */
import { css, jsx, keyframes } from '@emotion/react'
import React, { useState, useRef, useEffect, useCallback } from 'react';

import ModelHeader from './_ModelHeader';
import ModelMask from './_ModelMask';
import ModelContent from './_ModelContent';
import ModelActions from './_ModelActions';
import ModelContainer from './_ModelContianer';
import Draggable from './_Draggable';
import { ModelContext } from './_useModel';
import SThemeProvider from '../STheme/SThemeProvider';
import { useSTheme } from '../STheme/useToggleThemeHook';

function Model(props) {
    const {
        sizeMode = "sm", //弹窗的大小
        level = "default", // 弹窗的类型(主要是颜色类型),选项有:normal, error, warning, success, info
        title = "提示", //标题
        isDark,
        onClose,  //关闭弹窗后的回调
        enableDragging = true,
        enableController = true, //是否显示控制按钮
        content = "暂无弹窗内容", //弹窗内容
        actions = [ //操作按钮
            {
                title: "确定", //按钮标题
                attention: false, //是否为操作按钮
                onClick: (setLoading, setTitle, setDisable, onClose) => { onClose(); } //按钮回调
            },
        ],//功能按钮
    } = props;

    const [stateMode, setStateMode] = useState(1); // 弹窗的状态,0: 最小化, 1: 正常, 2: 最大化
    const theme = useSTheme(); //获取主题
    console.log(`theme => ${theme}`);

    return (
        <SThemeProvider isDark={isDark}>
            <ModelContext.Provider value={{
                stateMode, // 弹窗的状态,0: 最小化, 1: 正常, 2: 最大化
                setStateMode, // 设置弹窗的状态
                sizeMode, //弹窗最大宽度
                onClose, //关闭弹窗的回调
                isDark, //是否是暗黑模式
                level, // 弹窗的类型(主要是颜色类型),选项有:normal, error, warning, success, info
            }}>
                <ModelMask>
                    <Draggable
                        enableDragging={enableDragging && stateMode !== 2 }
                        enableHandler={true}
                        stateMode={stateMode}
                    >
                        <ModelContainer>
                            <ModelHeader
                                className=".model-handler"
                                title={title}
                                level={level}
                                onClose={onClose}
                                enableController={enableController}
                            />

                            {
                                content &&
                                <ModelContent>
                                    {
                                        content
                                    }
                                </ModelContent>
                            }

                            {
                                actions && actions.length > 0 &&
                                <ModelActions actions={actions} onClose={onClose} />
                            }
                        </ModelContainer>
                    </Draggable>
                </ModelMask>
            </ModelContext.Provider>
        </SThemeProvider>
    );
};

export default Model;

相关的内容前几节已经讲得很通透了。

下面我们来测试吧:

PopModelTest.jsx

javascript 复制代码
import React from 'react';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import useModel from '../../framework-kakaer/SModel/_useModel';
import Model from '../../framework-kakaer/SModel/_Model';

const longContent = `碧玉妆成一树高",写柳树给人的总体印象。柳树的形象美在于它那曼长披拂的枝条,一年一度,它长出了嫩绿的新叶,丝丝下垂,在春风吹拂中,有着一种迷人的意态。这里的"碧玉"既可指真实的玉,又暗含"碧玉小家女"(《碧玉歌》)中"碧玉"之意,指小户人家出身的年轻秀美的女子。古典诗词常借用柳树的形象美来形容美人苗条的身段、婀娜的腰肢,但此诗别出新意,翻转过来,将柳树化身为美人。用"碧玉"来比柳实际上有两层意思:一是"碧玉"和柳的颜色有关,"碧"和下句的"绿"是互相生发、互为补充的;二是"碧玉"这个人在人们头脑中留下的是年轻的印象,在古代文学作品里,"碧玉"几乎成了年轻貌美的女子的泛称。用"碧玉"来比柳,人们就会想象到这美人还未到丰容盛鬋的年华,这柳也还是早春稚柳,没有到密叶藏鸦的时候,同时和下文的"细叶""二月春风"又是有联系的。
"万条垂下绿丝绦",具体描写那茂密并轻柔下垂的柳枝,它是柳树最具代表性的部分。有了上句的铺垫,这千条万缕的垂丝,也随之变成了美人的裙带。上句的"高"字,衬托出美人婷婷袅袅的风姿;下句的"垂"字,暗示出纤腰在风中款摆。诗中没有"杨柳"和"腰肢"字样,然而这早春的垂柳以及柳树化身的美人,却给写活了。《南史》说刘悛之为益州刺史,献蜀柳数株,"条甚长,状若丝缕"。齐武帝把这些杨柳种植在太昌云和殿前,玩赏不置,说它"风流可爱"。这里把柳条说成"绿丝绦",可能是暗用这个关于杨柳的典故。但这里的化用,几乎看不出一点痕迹。
"不知细叶谁裁出,二月春风似剪刀。"这两句进一步细描细绘,刻画柳树的嫩叶。每一片树叶都造型别致,纹理细腻,仿佛都是精心裁剪而出。诗人由于惊叹不禁发问:这满树的细叶到底出自哪位高明的裁缝之手?接着找到了答案:原来是大自然的杰作,她手持二月春风这把大剪刀裁出了满树春色。绿叶好比美人衣裙上的花纹和图案,至此,那位美人便形神毕现地跃然纸上了。"二月春风似剪刀"这一新巧的比喻,把视之无形又不可捉摸的春风形象化地描绘出来。春风和剪刀,本来全不相干,它们的相同处只存在于诗人的想象之中。因此,"二月春风似剪刀"既新奇,又能唤起人们丰富的联想。
这首诗立意高远,比喻巧妙,先从大处着眼,然后分部描述,越写越细,把柳树的形神栩栩如生地表现了出来。题目是咏柳,但又不仅仅是咏柳,更是咏春,歌咏自然造化。全诗由"碧玉妆成"引出了"绿丝绦","绿丝绦"引出了"谁裁出",最后,那视之无形的不可捉摸的"春风",也被用"似剪刀"形象化地描绘了出来。这"剪刀"裁制出嫩绿鲜红的花花草草,给大地换上了新妆,它正是自然活力的象征,是春给予人们美的启示。从"碧玉妆成"到"剪刀",可以看出诗人一系列艺术构思的过程。诗歌里出现的一连串的形象,是一环紧扣一环的。`;

const normalContent = "唐玄宗天宝三载(744),贺知章奉诏告老回乡,百官送行。他坐船经南京、杭州,顺萧绍官河到达萧山县城,越州官员到驿站相迎,然后再坐船去南门外潘水河边的旧宅。此时正是二月早春,柳芽初发,春意盎然,微风拂面。贺知章如脱笼之鸟回到家乡,心情自然格外高兴,即景写下了这首诗。";

function PopModelTest() { 
    const alertDefault = useModel({
        title: "默认提示",
        content: normalContent,
        enableController: false,
    });
    const alertIno = useModel({
        title: "信息提示",
        level: "info",
        content: normalContent,
        enableController: false,
    });

    const alertSuccess = useModel({
        title: "成功提示",
        level: "success",
        content: normalContent,
        enableController: false,
    });

    const alertWarning = useModel({
        title: "警告提示",
        level: "warning",
        content: normalContent,
        enableController: false,
    });

    const alertError = useModel({
        title: "错误提示",
        level: "error",
        content: normalContent,
        enableController: false,
    });

    const alertLong = useModel({
        title: "长内容提示",
        content: longContent,
        enableController: false,
    });

    let initStatus = true;
    const alertLoading = useModel({
        title: "异步提交提示",
        content: normalContent,
        enableController: false,
        actions: [
            {
                title: "提交",
                attention: false,
                onClick: (setLoading, setTitle, setDisable, onClose) => {
                    if (initStatus) {
                        setLoading(true);
                        setTimeout(() => {
                            setLoading(false);
                            setTitle("提交成功, 可关闭");
                            initStatus = false;
                        }, 3000);
                    } else {
                        initStatus = true;
                        onClose();
                    }
                    

                }
            }
        ]
    });

    const alertMaxMin = useModel({
        title: "最大化最小化测试",
        level: "warning",
        content: normalContent,
        enableController: true,
        enableDragging: true,

    });

    const alertDrag = useModel({
        title: "拖动测试",
        level: "error",
        content: normalContent,
        enableController: false,
        enableDragging: true,
    });

    const morActionsAlert = useModel({
        title: "confirm测试",
        level: "info",
        content: normalContent,
        enableController: false,
        actions: [
            {
                title: "取消",
                attention: false,
                onClick: (setLoading, setTitle, setDisable, onClose) => {
                    onClose();
                }
            },
            {
                title: "确定",
                attention: true,
                onClick: (setLoading, setTitle, setDisable, onClose) => {
                    setLoading(true);
                    setTimeout(() => {
                        onClose();
                    }, 3000);
                    
                }
            }
        ]
    });

    return (
        <Stack spacing={2}>
            <Button
                variant='contained'
                onClick={() => { alertDefault(Model) }}
            >
                default 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertIno(Model) }}
            >
                info 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertError(Model) }}
            >
                error 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertWarning(Model) }}
            >
                warning 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertSuccess(Model) }}
            >
                success 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertLong(Model) }}
            >
                长文 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertLoading(Model) }}
            >
                loading 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { morActionsAlert(Model) }}
            >
                多Action 弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertDrag(Model) }}
            >
                可拖动弹窗
            </Button>

            <Button
                variant='contained'
                onClick={() => { alertMaxMin(Model) }}
            >
                可最大化最小化弹窗
            </Button>
        </Stack>
    )
}

export default PopModelTest;

本示例中所有的引入目录的位置请根据自己的项目做适当的调整。是不是很不错? 本弹窗系列到此完结。

相关推荐
弓.长.几秒前
React Native 鸿蒙跨平台开发:实现商品列表组件
react native·react.js·harmonyos
Dragon Wu7 分钟前
TailWindCss cva+cn管理样式
前端·css
烤麻辣烫12 分钟前
Web开发概述
前端·javascript·css·vue.js·html
Front思23 分钟前
Vue3仿美团实现骑手路线规划
开发语言·前端·javascript
徐同保25 分钟前
Nano Banana AI 绘画创作前端代码(使用claude code编写)
前端
Ulyanov26 分钟前
PyVista与Tkinter桌面级3D可视化应用实战
开发语言·前端·python·3d·信息可视化·tkinter·gui开发
计算机程序设计小李同学26 分钟前
基于Web和Android的漫画阅读平台
java·前端·vue.js·spring boot·后端·uniapp
lkbhua莱克瓦2429 分钟前
HTML与CSS核心概念详解
前端·笔记·html·javaweb
沛沛老爹30 分钟前
从Web到AI:Agent Skills CI/CD流水线集成实战指南
java·前端·人工智能·ci/cd·架构·llama·rag
弓.长.38 分钟前
React Native 鸿蒙跨平台开发:i18n 国际化方案代码指南
react native·react.js·harmonyos