Vue3+Element Plus实现自定义弹窗组件的全屏功能
作者:阳光的男夹克
在现代化的前端开发中,弹窗组件是提升用户体验的重要元素,本文将介绍如何使用 Vue 3 和 Element Plus 库来创建一个具有全屏功能的自定义弹窗组件,文中通过代码示例讲解的非常详细,需要的朋友可以参考下
组件概述
我们将构建一个名为 Dialog
的 Vue 组件,该组件具备以下特性:
- 自定义头部,包括全屏和关闭按钮
- 支持全屏和还原功能
- 可配置的弹窗尺寸和位置
- 拖拽功能(可选)
- 动态内容区域高度
以下是实现自定义弹窗组件的详细步骤和代码示例。
组件实现
1. 组件模板
我们使用 el-dialog
作为基础组件,并自定义了 header
插槽以添加全屏按钮和关闭图标。
<template> <el-dialog :dialogHeight="dialogHeight" :title="dialogTitle" class="dialog min-w-70" v-model="dialogVisible" append-to-body :modal="dialogModal" :fullscreen="fullscreen" :close-on-click-modal="dialogClickModalClose" :draggable="dialogDraggable" :show-close="false" :width="dialogWidth" :align-center="dialogAlignCenter" :center="dialogContentCenter" @open="open" @close="close" > <template #header> <div class="flex justify-between items-content"> <div class="titleClass">{{ dialogTitle }}</div> <div class="icon-content"> <!-- <el-icon class="single-uploader__icon text-[12px]"> <i-ep-minus v-if="fullscreen" /> <i-ep-plus v-else /> </el-icon>--> <div :title="!fullscreen ? '全屏' : '还原'"> <svg-icon class="icon-item-content" v-if="showExpand" @click="zoom" :icon-class="fullscreen ? 'fullscreen-exit' : 'fullscreen'" /> </div> <div title="关闭"> <el-icon v-if="showClose" @click="close" title="关闭" class="single-uploader__icon icon-item-content" > <i-ep-close /> </el-icon> </div> </div> </div> </template> <div :style="{ height: dialogBodyHeight }" class="overflow-auto"> <slot></slot> </div> <template #footer v-if="dialogFooterBtn"> <el-button type="primary" @click="SaveSubmit">确 定</el-button> <el-button @click="CloseSubmit">取 消</el-button> </template> </el-dialog> </template>
2. 组件脚本
在脚本部分,我们定义了组件的 props、slots 和 emits,以及一些必要的响应式数据和函数。
<script setup lang="ts"> // 【接口】接受传参字段 interface IProps { // 是否显示 Dialog visible: boolean; // 对话框的标题 dialogTitle?: string; // 内容区域高度 dialogHeight?: string; // 对话框的宽度 dialogWidth?: string; // 是否需要遮罩层 dialogModal?: boolean; // 是否水平垂直对齐对话框 dialogAlignCenter?: boolean; // 是否让 Dialog 的 header 和 footer 部分居中排列 dialogContentCenter?: boolean; // 是否可以通过点击 modal 关闭 Dialog dialogClickModalClose?: boolean; // 为 Dialog 启用可拖拽功能 dialogDraggable?: boolean; // 是否显示底部按钮 dialogFooterBtn?: boolean; // 是否显示全屏按钮 showExpand?: boolean; // 是否显示关闭按钮 showClose?: boolean; } // 初始化默认参数 const props = withDefaults(defineProps<IProps>(), { dialogTitle: "默认标题", dialogWidth: "40%", dialogHeight: "auto", dialogModal: true, dialogAlignCenter: false, dialogContentCenter: false, dialogClickModalClose: false, dialogDraggable: false, dialogFooterBtn: true, showExpand: false, showClose: true, }); const emit = defineEmits([ "save", "cancellation", "open", "close", "zoom", "update:visible", ]); const dialogVisible = useVModel(props, "visible", emit); let fullscreen = ref(false); const dialogBodyHeight = ref<string | number>(); // 初始值为字符串类型 // watch监听 watch( [() => props.visible, () => props.dialogHeight, () => props.dialogFooterBtn], () => { nextTick(() => { menuDialogZoom(); }); }, { deep: true, immediate: true } ); // 保存提交回调函数 const SaveSubmit = () => { emit("save"); //emit方法供父级组件调用 }; // 取消保存回调函数 const CloseSubmit = () => { emit("cancellation"); //emit方法供父级组件调用 }; // 打开事件回调函数 const open = () => { emit("open"); //emit方法供父级组件调用 }; // 关闭事件回调函数(当显示头部关闭按钮时需调用该回调函数方法 -> dialogShowClose = true 反之) const close = () => { emit("close"); //emit方法供父级组件调用 }; // 缩放弹窗 const zoom = () => { fullscreen.value = !fullscreen.value; menuDialogZoom(); console.log(fullscreen.value); emit("zoom", fullscreen.value); //emit方法供父级组件调用 }; /* 分配权限缩放弹窗 */ const menuDialogZoom = () => { if (props.visible && fullscreen.value && props.dialogFooterBtn) { dialogBodyHeight.value = "calc(100vh - 120px)"; } else if (props.visible && fullscreen.value && !props.dialogFooterBtn) { dialogBodyHeight.value = "calc(100vh - 80px)"; } else { dialogBodyHeight.value = props.dialogHeight; } }; </script>
3. 组件样式
<style scoped> .titleClass { font-weight: bold; } .icon-content { display: flex; align-items: center; } .icon-item-content { display: flex; align-items: center; justify-content: center; color: #909399; } .icon-item-content:nth-child(1) { margin-right: 10px; } .icon-item-content:hover { color: #1f6feb; cursor: pointer; } .single-uploader__icon { font-size: 18px; } </style>
4. 使用案例
以下是如何在父组件中使用 Dialog
组件的示例,包括如何传递参数和处理事件。
<Dialog dialogHeight="350px" v-model:visible="menuDialogVisible" :dialogTitle="'【' + checkedRole.name + '】权限分配'" :dialogDraggable="true" dialogWidth="30%" @close="menuDialogVisible = false" @save="handleRoleMenuSubmit" @cancellation="menuDialogVisible = false" > 内容区域 </Dialog>
5. 弹窗相关数据
定义了控制弹窗显示的响应式数据。
let menuDialogVisible = ref(false);
关键功能实现
自定义头部
我们通过 header
插槽来自定义弹窗的头部,增加了全屏切换按钮和关闭按钮。
<template #header> <!-- 省略部分代码,详见完整代码示例 --> </template>
全屏和还原功能
通过点击全屏按钮,我们可以切换弹窗的全屏状态。这一功能通���修改 fullscreen
响应式数据实现。
const zoom = () => { fullscreen.value = !fullscreen.value; menuDialogZoom(); emit("zoom", fullscreen.value); };
动态内容区域高度
根据弹窗的全屏状态和是否显示底部按钮,我们动态计算内容区域的高度。
const menuDialogZoom = () => { // 省略部分代码,详见完整代码示例 };
结论
通过以上步骤,我们创建了一个功能丰富、高度可配置的自定义弹窗组件。这个组件可以根据实际需求调整尺寸、位置和内容,非常适合在复杂的应用场景中使用。希望这篇文章能帮助您在项目中更好地利用 Vue 3 和 Element Plus 库。如果您有任何疑问或建议,欢迎在评论区留言交流。
以上就是Vue3+Element Plus实现自定义弹窗组件的全屏功能的详细内容,更多关于Vue3 Element Plus弹窗组件全屏的资料请关注脚本之家其它相关文章!