二次封装 el-dialog 组件:打造更灵活的对话框解决方案

文章目录

  • 引言
    • 为什么需要二次封装?
    • 封装思路
    • 代码实现
      • 1. 基础封装组件 (Dialog.vue)
      • 2. Vue中引入使用示例
    • 封装后的优势
    • 进阶优化建议
  • 总结


引言

在 Vue 项目中,Element UI 的 el-dialog 是一个非常实用的对话框组件。但在实际开发中,我们经常会遇到需要重复设置对话框属性、处理相同逻辑的情况。通过二次封装,我们可以创建一个更灵活、更易用的对话框组件,提高开发效率并保持代码一致性。

为什么需要二次封装?

  1. 减少重复代码:多个对话框可能需要相同的逻辑(如关闭确认、表单重置等)
  2. 统一风格:确保所有对话框的视觉和交互行为一致
  3. 简化使用:通过默认值和封装方法,减少每次使用时需要编写的代码
  4. 增强功能:添加常用功能如加载状态、国际化支持等

封装思路

我们将创建一个 Dialog 组件,它封装了那些扩展?:

  • 封装了 el-dialog 的常用属性和事件
  • 动态按钮大小,按钮标题动态展示,按钮的type类型
  • 弹窗的动态宽度
  • 是否显示关闭,取消按钮
  • 添加了确认关闭逻辑
  • 支持插槽内容(内容根据项目随意调整)
  • 提供统一的关闭方法
  • 批量按钮的动态添加
  • 窗口的响应式

代码实现

1. 基础封装组件 (Dialog.vue)

<template><div><el-dialogclass="cust-dialog":model-value="show":title="title":width="dialogWidth":top="top + 'px'"@close="close":draggable="true":show-close="showClose":modal-class="'dialog-fade'"><divclass="dialog-body"><slot></slot></div><template #footer><span class="dialog-footer"><slot name="footer"><!-- 默认footer内容 --><el-button type="danger" @click="close" v-if="showCancel">取消</el-button><el-buttonv-for="item in buttons"@click="item.click":type="item.type || primary":size="item.size">{{ item.text }}</el-button></slot></span></template></el-dialog></div>
</template><script setup lang="ts">
import { computed, watch, onMounted, onUnmounted, ref } from "vue";
const props = defineProps<{show: { type: Boolean; default: false };title: { type: String; default: "提示" };width: { type: String; default: "30%" };top: { type: Number; default: 50 };padding: { type: Number; default: 15 };showClose: { type: Boolean; default: true };showCancel: { type: Boolean; default: true };buttons: {type: Array<{text: string;click: () => void;type?: "primary" | "success" | "warning" | "danger" | "info";size?: "large" | "small" | "default";}>;default: () => [];};
}>();const dialogWidth = ref(props.width);
// 监听窗口大小变化,根据窗口宽度动态设置dialog宽度
onMounted(() => {const handleResize = () => {if (window.innerWidth <= 768) {dialogWidth.value = "50%";} else {dialogWidth.value = props.width;}};window.addEventListener("resize", handleResize);
});onUnmounted(() => {window.removeEventListener("resize", handleResize);
});const emit = defineEmits(["close"]);
const close = () => {emit("close");
};
</script><style lang="scss">
@keyframes fade {from {opacity: 0;}to {opacity: 1;}
}.dialog-fade {animation: fade 0.3s;
}.cust-dialog {margin: 30px auto 10px !important;.el-dialog__body {padding: 0px;}.dialog-body {border-top: 1px solid #ddd;border-bottom: 1px solid #ddd;min-height: 80px;overflow: auto;/* 自定义滚动条 */&::-webkit-scrollbar {width: 3px;height: 8px;}&::-webkit-scrollbar-track {background: #f1f1f1;border-radius: 4px;}&::-webkit-scrollbar-thumb {background: #c1c1c1;border-radius: 4px;transition: background 0.3s;&:hover {background: #a8a8a8;}}}.dialog-footer {text-align: right;padding: 5px 20px;}
}
</style>

2. Vue中引入使用示例

<template><div><Dialog:show="dialogConfig.show":title="dialogConfig.title":width="dialogConfig.width":top="dialogConfig.top":padding="dialogConfig.padding":showClose="dialogConfig.showClose":showCancel="dialogConfig.showCancel":buttons="dialogConfig.buttons"@close="dialogConfig.show = false"><el-form :model="form" label-width="auto" style="max-width: 600px"><el-form-item label="Activity name"><el-input v-model="form.name" /></el-form-item><el-form-item label="Activity zone"><el-selectv-model="form.region"placeholder="please select your zone"><el-option label="Zone one" value="shanghai" /><el-option label="Zone two" value="beijing" /></el-select></el-form-item><el-form-item label="Activity time"><el-col :span="11"><el-date-pickerv-model="form.date1"type="date"placeholder="Pick a date"style="width: 100%"/></el-col><el-col :span="2" class="text-center"><span class="text-gray-500">-</span></el-col><el-col :span="11"><el-time-pickerv-model="form.date2"placeholder="Pick a time"style="width: 100%"/></el-col></el-form-item><el-form-item label="Instant delivery"><el-switch v-model="form.delivery" /></el-form-item><el-form-item label="Activity type"><el-checkbox-group v-model="form.type"><el-checkbox value="Online activities" name="type">Online activities</el-checkbox><el-checkbox value="Promotion activities" name="type">Promotion activities</el-checkbox><el-checkbox value="Offline activities" name="type">Offline activities</el-checkbox><el-checkbox value="Simple brand exposure" name="type">Simple brand exposure</el-checkbox></el-checkbox-group></el-form-item><el-form-item label="Resources"><el-radio-group v-model="form.resource"><el-radio value="Sponsor">Sponsor</el-radio><el-radio value="Venue">Venue</el-radio></el-radio-group></el-form-item><el-form-item label="Activity form"><el-input v-model="form.desc" type="textarea" /></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">Create</el-button><el-button>Cancel</el-button></el-form-item></el-form></Dialog><el-button type="primary" @click="showDialog">点击</el-button></div>
</template><script setup lang="ts">
import Dialog from "@/components/Dialog.vue";
import { ref, reactive } from "vue";
const dialogConfig = ref({show: false, // 控制弹窗显示title: "测试弹窗", // 标题width: "80%", // 宽度top: 50, // 距离顶部高度padding: 15, // 内容内边距showClose: true, // 是否显示关闭按钮showCancel: true, // 是否显示取消按钮buttons: [{text: "确定",click: () => console.log("确定"),type: "success",size: "default",},],
});const showDialog = () => {dialogConfig.value.show = true;
};const form = reactive({name: "",region: "",date1: "",date2: "",delivery: false,type: [],resource: "",desc: "",
});const onSubmit = () => {console.log("submit!");
};
</script><style lang="scss" scoped></style>

效果:
在这里插入图片描述

封装后的优势

  1. 统一配置:所有对话框共享相同的配置项,如关闭行为、按钮文本等

  2. 简化使用:只需关注对话框内容,无需重复设置相同属性

  3. 增强功能

    • 内置加载状态
    • 统一的确认/取消逻辑
    • 可选的关闭前确认
  4. 更好的可维护性:所有对话框逻辑集中在一个组件中

  5. 灵活性

    • 保留 el-dialog 的所有属性和事件(通过 $attrs 透传)
    • 支持插槽自定义内容
    • 支持自定义底部按钮

进阶优化建议

  1. 国际化支持:将按钮文本等可配置项提取到语言包中
  2. 主题定制:通过 CSS 变量或 props 允许自定义样式
  3. 动画效果:添加自定义进入/离开动画
  4. 表单验证集成:如果主要用于表单,可以集成表单验证逻辑
  5. 响应式宽度:根据内容自动调整宽度

总结

通过对 el-dialog 的二次封装,我们创建了一个更强大、更易用的对话框组件。这不仅减少了重复代码,还提高了开发效率和代码一致性。在实际项目中,可以根据团队需求进一步扩展这个基础组件,添加更多实用功能。

希望这个封装方案能为你的 Vue 项目开发带来便利!如果你有任何改进建议或使用中的问题,欢迎在评论区交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

框架篇八股(自用)

框架篇 Spring框架中的bean不是线程安全的 Scope&#xff08;&#xff09; singleton单例 prototype多例 一个类中有可修改的成员变量需要考虑线程安全 bean没有可变状态&#xff08;service类&#xff0c;DAO类&#xff09; 某种程度单例bean是线程安全的 AOP面向切面编程…

Go语言安装proto并且使用gRPC服务(2025最新WINDOWS系统)

1.protobuf简介 protobuf 即 Protocol Buffers&#xff0c;是一种轻便高效的结构化数据存储格式&#xff0c;与语言、平台无关&#xff0c;可扩展可序列化。protobuf 性能和效率大幅度优于 JSON、XML 等其他的结构化数据格式。protobuf 是以二进制方式存储的&#xff0c;占用空…

rust-candle学习笔记11-实现一个简单的自注意力

参考&#xff1a;about-pytorch 定义ScaledDotProductAttention结构体&#xff1a; use candle_core::{Result, Device, Tensor}; use candle_nn::{Linear, Module, linear_no_bias, VarMap, VarBuilder, ops};struct ScaledDotProductAttention {wq: Linear,wk: Linear,wv: …

spark MySQL数据库配置

Spark 连接 MySQL 数据库的配置 要让 Spark 与 MySQL 数据库实现连接&#xff0c;需要进行以下配置步骤。下面为你提供详细的操作指南和示例代码&#xff1a; 1. 添加 MySQL JDBC 驱动依赖 你得把 MySQL 的 JDBC 驱动添加到 Spark 的类路径中。可以通过以下两种方式来完成&a…

web 自动化之 KDT 关键字驱动详解

一、什么是关键字驱动&#xff1f; 1、什么是关键字驱动&#xff1f;&#xff08;以关键字函数驱动测试&#xff09; 关键字驱动又叫动作字驱动&#xff0c;把项目业务封装成关键字函数&#xff0c;再基于关键字函数实现自动化测试 2、关键字驱动测试原理 关键字驱动测试是一…

Java使用POI+反射灵活的控制字段导出Excel

前端传入哪些字段&#xff0c;后端就导出哪些到Excel表格中&#xff0c;具体代码实现如下 controller /*** 用户导出* param dto*/PostMapping("/exportUser")public void exportCharterOrder(RequestBody UserExportDTO dto){userService.exportUser(dto);} serv…

Qt/C++面试【速通笔记八】—Qt的事件处理机制

在Qt中&#xff0c;事件处理机制是应用程序与用户或系统交互的核心。通过事件处理&#xff0c;Qt能够响应用户的输入、窗口的变化、定时器的触发等各种情况。 1. 事件循环&#xff08;Event Loop&#xff09; 在Qt应用程序中&#xff0c;事件循环是事件处理机制的基础。事件循…

TTL (Time-To-Live) 解析

文章目录 TTL (Time-To-Live) 解析&#xff1a;网络与Java中的应用一、TTL的定义二、TTL在网络中的应用1. **路由和数据包的生命周期**2. **DNS中的TTL**3. **防止环路** 三、TTL在Java中的应用1. **缓存管理**2. **Java中的ThreadLocal**3. **网络通信中的TTL** 四、TTL的注意…

HDFS的客户端操作(2)文件上传

我们向/maven下上传一个文件。 要用到的api是put (或者copyFormLocalFile&#xff09;。核心代码如下。 public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {// 1 获取文件系统Configuration configuration new Configurati…

光谱相机的光电信号转换

光谱相机的光电信号转换是将分光后的光学信息转化为可处理的数字信号的核心环节&#xff0c;具体分为以下关键步骤&#xff1a; 一、分光后光信号接收与光电转换 ‌分光元件作用‌ 光栅/棱镜/滤光片等分光元件将入射光分解为不同波长单色光&#xff0c;投射至探测器阵列表面…

网络协议分析 实验二 IP分片与IPv6

文章目录 索引及重要内容实验2 IP 高级实验实验2.1 IPv4协议分片实验实验2.2 IPV6协议实验2.3 ARP初级 索引及重要内容 实验2 IP 高级实验 实验2.1 IPv4协议分片实验 icmp的不可达报文 实验2.2 IPV6协议 实验2.3 ARP初级 arp –a 查看ARP缓存表内容 arp –s IP地址(格式&…

20、map和set、unordered_map、un_ordered_set的复现

一、map 1、了解 map的使用和常考面试题等等&#xff0c;看这篇文章 map的key是有序的 &#xff0c;值不可重复 。插入使用 insert的效率更高&#xff0c;而在"更新map的键值对时&#xff0c;使用 [ ]运算符效率更高 。" 注意 map 的lower和upper那2个函数&#x…

基于 Amazon Bedrock 和 Amazon Connect 打造智能客服自助服务 – 设计篇

随着 GenAI 技术不断的发展和演进&#xff0c;人工智能技术广泛地被应用在呼叫中心服务领域&#xff0c;主要包括虚拟坐席&#xff08;即自助服务&#xff09;、坐席助手和呼叫中心运营的数据洞察和智能分析。本博客主要针对自助服务应用场景的实现。 1. 传统自助服务系统瓶颈 …

java高效实现爬虫

一、前言 在Web爬虫技术中&#xff0c;Selenium作为一款强大的浏览器自动化工具&#xff0c;能够模拟真实用户操作&#xff0c;有效应对JavaScript渲染、Ajax加载等复杂场景。而集成代理服务则能够解决IP限制、地域访问限制等问题。本文将详细介绍如何利用JavaSelenium快代理实…

【计算机视觉】OpenCV实战项目:基于OpenCV的车牌识别系统深度解析

基于OpenCV的车牌识别系统深度解析 1. 项目概述2. 技术原理与算法设计2.1 图像预处理1) 自适应光照补偿2) 边缘增强 2.2 车牌定位1) 颜色空间筛选2) 形态学操作3) 轮廓分析 2.3 字符分割1) 投影分析2) 连通域筛选 2.4 字符识别 3. 实战部署指南3.1 环境配置3.2 项目代码解析 4.…

Python核心数据类型全解析:字符串、列表、元组、字典与集合

导读&#xff1a; Python 是一门功能强大且灵活的编程语言&#xff0c;而其核心数据类型是构建高效程序的基础。本文深入剖析了 Python 的五大核心数据类型——字符串、列表、元组、字典和集合&#xff0c;结合实际应用场景与最佳实践&#xff0c;帮助读者全面掌握这些数据类型…

GPT-4.1和GPT-4.1-mini系列模型支持微调功能,助力企业级智能应用深度契合业务需求

微软继不久前发布GPT-4.1系列模型后&#xff0c;Azure OpenAI服务&#xff08;国际版&#xff09;现已正式开放对GPT-4.1和GPT-4.1-mini的微调功能&#xff0c;并通过Azure AI Foundry&#xff08;国际版&#xff09;提供完整的部署和管理解决方案。这一重大升级标志着企业级AI…

构造+简单树状

昨日的牛客周赛算是比较简单的&#xff0c;其中最后一道构造题目属实眼前一亮。 倒数第二个题目也是一个很好的模拟题目&#xff08;考验对二叉树的理解和代码的细节&#xff09; 给定每一层的节点个数&#xff0c;自己拟定一个父亲节点&#xff0c;构造一个满足条件的二叉树。…

apache2的默认html修改

使用127.0.0.1的时候&#xff0c;默认打开的是index.html&#xff0c;可以通过配置文件修改成我们想要的html vi /etc/apache2/mods-enabled/dir.conf <IfModule mod_dir.c>DirectoryIndex WS.html index.html index.cgi index.pl index.php index.xhtml index.htm <…

mysql性能提升方法大汇总

前言 最近在开发自己的小程序的时候&#xff0c;由于业务功能对系统性能的要求很高&#xff0c;系统性能损耗又主要在mysql上&#xff0c;而业务功能的数据表很多&#xff0c;单表数据量也很大&#xff0c;又涉及到很多场景的数据查询&#xff0c;所以我针对mysql调用做了优化…