UseElDialog - 对话框
组件介绍
UseElDialog 是基于 Element Plus 的el-dialog组件进行二次封装的通用对话框组件,旨在解决原生el-dialog在中后台项目开发中存在的配置繁琐、样式不统一、事件逻辑混乱、扩展成本高等问题。该组件通过封装通用配置、统一样式规范、优化事件处理逻辑、预留灵活扩展入口,大幅提升对话框开发效率,同时保证组件的通用性与可定制性,适配中后台系统各类弹窗交互场景。
核心亮点
- 配置化驱动,减少重复编码:将 el-dialog 高频配置(如标题、是否点击遮罩关闭、销毁策略等)封装为标准化 props,无需在每个弹窗页面重复编写 el-dialog 基础属性,仅需通过 props 传入差异化配置即可快速生成对话框。
- 样式统一且支持个性化定制:内置统一的头部、主体、底部样式规范,同时通过 CSS 变量 + 样式配置项(headerStyleConfig、footerPosition)支持个性化调整,兼顾系统风格一致性与业务定制需求。
- 事件逻辑精细化管控:区分手动操作(确认 / 取消按钮)与自动关闭(右上角关闭、遮罩点击)场景,优化 close/cancel 事件触发逻辑,支持严格区分 close 事件,避免原生组件事件触发混乱的问题。
- 灵活的布局与扩展能力:内置滚动容器、自定义头部 / 底部插槽、footer 自定义模式(默认 / 自定义),适配不同内容展示、操作按钮布局的需求,无需破坏组件结构即可扩展功能。
- 性能优化细节:默认开启 destroyOnClose 减少内存占用,el-scrollbar 支持 noresize 配置优化渲染性能,appendToBody 规避嵌套弹窗层级问题。
解决痛点
- 原生 el-dialog 样式定制繁琐且不统一
- 痛点:原生 el-dialog 的头部、底部样式需手动编写自定义样式覆盖,不同页面的弹窗表头背景、文字颜色、底部对齐方式等样式不统一,且嵌套弹窗样式易受父容器影响,样式调试成本高。
- 解决方案:组件内置统一的头部 / 底部样式(如表头边框、内边距、关闭按钮位置),通过 CSS 变量(--wyfe-ivue__dialog-header-bg 等)和 props(headerStyleConfig、footerPosition)集中管理样式属性,仅需配置即可调整样式,同时默认开启 appendToBody 规避嵌套样式污染问题,保证样式一致性。
- 原生 el-dialog 事件逻辑混乱,关闭行为不可控
- 痛点:原生 el-dialog 的 closed 事件无法区分 “点击取消按钮”“点击右上角关闭”“点击遮罩关闭” 等场景,不同关闭行为需手动判断来源,且 close/cancel 事件易混淆,导致关闭逻辑处理混乱,不同开发者实现方式不一致。
- 解决方案:组件封装 handleClosed 统一处理关闭逻辑,通过 isManualOperate 区分手动操作(确认 / 取消按钮)与自动关闭,结合 strictCloseEvent 配置项可严格区分 onClose(右上角关闭)与 onCancel(取消按钮 / 默认关闭)事件,确保不同关闭场景的逻辑可精准管控,无需重复编写事件判断代码。
- 弹窗内容滚动、布局需重复封装
- 痛点:每个弹窗需手动封装 el-scrollbar 处理内容滚动,且需调整滚动容器样式适配 dialog 内边距,底部按钮区域(footer)的对齐方式、边框样式需重复编写,开发效率低。
- 解决方案:组件内置 el-scrollbar 作为内容容器,支持 maxHeight、noresize 配置优化滚动体验,同时封装 footer 区域的默认样式(边框、内边距)和对齐方式配置,默认提供确认 / 取消按钮,也支持 CUSTOM 模式自定义 footer 内容,减少 80% 以上的布局重复代码。
- 原生 el-dialog 高频配置重复编写
- 痛点:中后台项目中每个弹窗需重复配置 appendToBody、closeOnClickModal、destroyOnClose 等属性,且默认值不统一(如部分弹窗忘记开启 destroyOnClose 导致内存泄漏),配置遗漏易引发线上问题。
- 解决方案:组件将高频配置封装为 props 并设置合理默认值(如默认 appendToBody: true、destroyOnClose: true、closeOnClickModal: false),无需每个页面重复配置,同时通过 props 校验(如 footerPosition 仅支持 left/center/right)避免配置错误,降低开发失误率。
- 扩展自定义内容时易破坏组件原有逻辑
- 痛点:原生 el-dialog 自定义头部、底部内容时,需替换默认的 header/footer 插槽,易导致原有样式、事件逻辑失效(如自定义 header 后关闭按钮样式丢失),且自定义按钮需手动处理关闭逻辑,与原有关闭行为冲突。
- 解决方案:组件预留 header、footer 插槽(showHeader 控制是否显示默认头部,showFooter 支持 CUSTOM 模式自定义底部),自定义内容时不会覆盖原有样式和事件逻辑;同时封装 handleClick 方法统一处理按钮点击逻辑,确保自定义按钮的关闭行为与组件原有逻辑一致,扩展功能时无需担心冲突。
使用案例
ComponentProps
js
import type { PropType } from 'vue'
/**
* 组件props
*/
export default {
/**
* el-dialog的标题
*/
title: {
type: String,
default: '欢迎使用wyfe-ivue对话框组件'
},
/**
* el-dialog自身是否插入至body元素上。嵌套的el-dialog必须指定该属性并赋值为 true 默认是
*/
appendToBody: {
type: Boolean,
default: true
},
/**
* el-dialog头部区域样式配置
*/
headerStyleConfig: {
type: Object as PropType<Record<string, any>>,
default: () => ({ bgColor: 'var(--theme-color)', color: '#fff' })
},
/**
* el-dialog内容区域最大高度
*/
maxHeight: {
type: [String, Number],
default: ''
},
/**
* el-scrollbar不响应容器尺寸变化,如果容器尺寸不会发生变化,最好设置它可以优化性能
*/
noresize: {
type: Boolean,
default: true
},
/**
* 是否可以通过点击modal关闭el-dialog 默认否
*/
closeOnClickModal: {
type: Boolean,
default: false
},
/**
* 控制是否在关闭el-dialog后将子元素全部销毁 默认是
*/
destroyOnClose: {
type: Boolean,
default: true
},
/**
* 是否显示header 默认显示
*/
showHeader: {
type: Boolean,
default: true
},
/**
* 是否显示footer 默认显示,为CUSTOM可自定义footer
*/
showFooter: {
type: [Boolean, String],
default: true,
validator: (val: boolean | string) => [true, false, 'CUSTOM'].includes(val)
},
/**
* 底部定位 默认right
*/
footerPosition: {
type: String,
default: 'right',
validator: (val: string) => ['left', 'center', 'right'].includes(val)
},
/**
* 是否严格区分close事件 默认否 和onClose事件二选一设置一个即可
*/
strictCloseEvent: {
type: Boolean,
default: false
},
/**
* 抽屉关闭图标事件 若未设置且未开启strictCloseEvent则默认执行onCancel事件
*/
onClose: {
type: Function,
default: () => {}
},
/**
* 确定按钮文本
*/
confirmBtnText: {
type: String,
default: '保存'
},
/**
* 取消按钮文本
*/
cancelBtnText: {
type: String,
default: '取消'
},
/**
* 取消按钮类型
*/
cancelBtnType: {
type: String,
default: '',
validator: (val: string) =>
[
'',
'default',
'primary',
'success',
'warning',
'danger',
'info'
].includes(val)
},
/**
* 确定按钮事件
*/
onConfirm: {
type: Function,
default: () => {}
},
/**
* 取消按钮事件
*/
onCancel: {
type: Function,
default: () => {}
}
}Props && Expose
js
const props = defineProps(componentProps)
defineExpose({ edRef, handleClose })