自定义vue3函数式弹窗

vue文件,用于编写弹窗组件样式

html 复制代码
<template>
    <div class='custom_pop_container'>
        <!-- 遮罩层 -->
        <div class='mask_layer'></div>
        <!-- 弹窗内容 -->
        <div class="custom_pop_content">
            <!-- 标题 -->
            <div class="custom_pop_title">
                <img :src="iconUrl" class="pop_icon_box">
                {{ title }}
            </div>
            <!-- 内容 -->
            <div class="custom_pop_content_text">{{ content }}</div>
            <!-- 按钮 -->
            <div class="custom_pop_content_buttons">
                <button class="cancel_button button_style" @click="onCancel">{{ cancelButtonText }}</button>
                <button class="confirm_button button_style" @click="onConfirm">{{ confirmButtonText }}</button>
            </div>
        </div>
    </div>
</template>
<script setup lang='ts'>
// 响应式数据
import { getAssetsFile } from '@/utils/utils';
import { ref, reactive, computed, watch } from 'vue'
interface IProps {
    title: string;
    content: string;
    iconUrl?: string;
    confirmButtonText?: string;
    cancelButtonText?: string;
    showFooter?: boolean;
    onConfirm?: () => void;
    onCancel?: () => void;
}
const props = withDefaults(defineProps<IProps>(), {
    content: '',
    iconUrl: getAssetsFile('chat/pop_icon.png'),
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    showFooter: true,
    onConfirm: () => { },
    onCancel: () => { },
})
</script>


<style scoped lang='scss'>
.custom_pop_container {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1000;

    .mask_layer {
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.4);
        position: absolute;
        top: 0;
        left: 0;
    }

    .custom_pop_content {
        width: 418px;
        background-color: #F8F9FB;
        border-radius: 12px;
        padding: 24px 20px 20px 20px;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);

        .custom_pop_title {
            display: flex;
            align-items: center;
            font-weight: 500;
            font-size: 16px;
            color: #303133;
            line-height: 24px;
            margin-bottom: 20px;

            .pop_icon_box {
                width: 16px;
                height: 16px;
                object-fit: cover;
                margin-right: 4px;
            }
        }

        .custom_pop_content_text {
            font-weight: 400;
            font-size: 14px;
            color: #303133;
            line-height: 22px;
        }

        .custom_pop_content_buttons {
            display: flex;
            justify-content: flex-end;
            column-gap: 12px;
            margin-top: 40px;

            .button_style {
                display: inline-flex;
                justify-content: center;
                align-items: center;
                width: 68px;
                height: 32px;
                padding: 8px 15px;
                font-size: 14px;
                font-weight: 500;
                line-height: 1;
                border-radius: 4px;
                border: 1px solid;
                cursor: pointer;
                outline: none;
                transition: 0.1s;
                appearance: none;
                -webkit-appearance: none;
                box-sizing: border-box;
            }

            .cancel_button {
                color: #606266;
                background-color: #fff;
                border-color: #dcdfe6;

                &:hover {
                    color: #409eff;
                    border-color: #c6e2ff;
                    background-color: #ecf5ff;
                }

                &:active {
                    color: #3a8ee6;
                    border-color: #3a8ee6;
                    background-color: #d9ecff;
                }
            }

            .confirm_button {
                color: #fff;
                background-color: #409eff;
                border-color: #409eff;

                &:hover {
                    background-color: #66b1ff;
                    border-color: #66b1ff;
                }

                &:active {
                    background-color: #3a8ee6;
                    border-color: #3a8ee6;
                }
            }
        }
    }
}
</style>

ts文件,把弹窗组件渲染出来

typescript 复制代码
import CustomPopCom from './CustomPopCom.vue';
import { createVNode, render } from 'vue';
let customPopDom = null;
export const useCustomPop = (userOptions: any) => {
    let options = {
        ...userOptions,
    }
    options.onCancel = () => {
        userOptions.onCancel && userOptions.onCancel();  //用户的关闭函数
        closeCustomPop();
    }
    options.onConfirm = () => {
        userOptions.onConfirm && userOptions.onConfirm();  //用户的确认函数
        closeCustomPop();
    }
    // 获取到虚拟dom
    const vnode = createVNode(CustomPopCom, options);
    customPopDom = document.createElement('div');
    render(vnode, customPopDom);
    // 渲染到body中
    document.body.appendChild(customPopDom);
}
export const closeCustomPop = () => {
    customPopDom && document.body.removeChild(customPopDom);
}

在vue文件中使用

typescript 复制代码
useCustomPop({
        title: '删除会话',
        content: '删除后无法恢复,是否继续删除?',
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        onConfirm: () => {
            deleteAgentChat({
                user_id: userStore.userInfo?.id,
                session_id: item.session_id,
            }).then(res => {
                ElMessage.success("删除会话成功");
                getGroupChatListFun();
            })
        },
    })
相关推荐
IT_陈寒几秒前
Redis客户端连接池不关闭的后果,程序直接崩给我看
前端·人工智能·后端
怕浪猫1 分钟前
Electron 开发实战(九):调试技巧与开发者工具|测试、性能分析、日志追踪全解
前端·javascript·electron
喜欢踢足球的老罗4 分钟前
产品方案:从已有 CRM AI 系统切入 WhatsApp Chrome 插件赛道
前端·人工智能·chrome
无心使然5 分钟前
OpenLayers 10.9.0 渲染架构分析
前端·gis·数据可视化
智能制造产品经理代码提升6 分钟前
ES6+ 标准使用手册
前端·javascript·es6
xiaofeichaichai10 分钟前
ES6+ 模块
前端·ecmascript·es6
xuankuxiaoyao13 分钟前
阶段案例——后台管理系统
java·linux·前端
恋猫de小郭13 分钟前
Android 17 内存管理将严格管控,App 要注意适配
android·前端·flutter
暗冰ཏོ17 分钟前
《uni-app 跨端开发完整指南:从基础入门到 H5、小程序、App 发布上线》
前端·小程序·uni-app·vue·html5
搬砖的前端19 分钟前
AI工具集:Git提交时使用AI进行CodeReview如何在前端应用构建NPM包
前端·人工智能·git·npm·codeview