Skip to content

UseElDialog - 对话框

组件介绍

UseElDialog 是基于 Element Plus 的 ElDialog 二次封装的对话框组件,专注于为弹窗提供开箱即用的全屏切换、标准化滚动区域、智能事件管理能力,同时遵循中后台最佳实践配置默认值,完整兼容原生 ElDialog 核心属性与插槽,可直接替换原生 ElDialog 使用,大幅降低弹窗场景的重复开发成本。

核心能力

  1. 开箱即用的全屏切换能力

内置全屏切换功能(showFullScreenIcon),头部默认显示全屏图标,点击即可一键切换全屏 / 窗口模式,自动切换全屏 / 还原图标,全屏状态下自动适配内容区高度为 calc (100dvh - 154px),完美兼容移动端视口,无需手动处理全屏状态下的布局适配。

  1. 标准化的滚动区域处理

内置 el-scrollbar 组件包装内容区域,自动处理全屏与非全屏状态下的高度计算:非全屏时支持自定义 maxHeight,全屏时自动撑满可用高度,默认开启 noresize 性能优化(适用于弹窗尺寸固定场景),解决原生弹窗内容溢出时的滚动条样式不一致问题,内容区自动处理 padding 保证滚动条不遮挡内容。

  1. 规范的布局与动态样式系统

标准化头部、内容区、底部三栏布局,支持通过 props 动态控制头部分割线(showHeaderBottomBorder)、底部分割线(showFooterTopBorder)、底部按钮对齐方式(footerPosition 支持 left/center/right),使用 CSS 变量实现样式动态切换,无需 scoped 样式穿透即可灵活定制外观,同时统一处理弹窗 padding 负值问题,保证布局一致性。

  1. 智能的关闭事件管理

创新的关闭事件处理机制:支持 strictCloseEvent 严格模式区分关闭来源,右上角关闭按钮默认智能复用 onCancel 事件逻辑,也可通过 onClose 自定义关闭事件;自动区分底部按钮手动点击与关闭按钮触发场景,避免事件重复执行,解决原生弹窗关闭事件逻辑混乱问题。

  1. 内置防抖按钮能力

底部默认按钮自动集成 UseElButton 组件,开箱即带防抖能力,无需额外配置即可避免重复提交问题;默认提供 "保存"、"取消" 两个标准按钮,支持自定义按钮文本(confirmBtnText/cancelBtnText)、取消按钮类型(cancelBtnType),也可通过 footer 插槽完全自定义底部内容。

  1. 中后台最佳实践默认配置

遵循企业级中后台弹窗使用规范,默认开启最佳实践配置:appendToBody=true 解决嵌套弹窗层级问题、destroyOnClose=true 关闭时自动销毁子元素避免内存泄漏、closeOnClickModal=false 防止点击遮罩误触关闭,无需业务侧重复配置,统一项目内弹窗交互规范。

  1. 完整的原生兼容与扩展能力

基于 ElDialog 封装,完整保留 v-model 控制显隐等核心能力,header、default、footer 插槽完全透传,支持自定义头部、内容区、底部内容;通过 defineExpose 暴露内部 el-dialog 实例(edRef)和 handleClose 方法,可直接调用原生弹窗所有能力,无迁移成本,同时补充原生弹窗缺失的全屏、智能事件等能力。

  1. 精细化的交互体验优化

内置多处体验优化:全屏图标 hover 透明度与颜色过渡、关闭按钮 hover 主题色效果、内容区滚动条样式适配、头部底部边框统一处理、关闭按钮位置微调,解决原生 ElDialog 在不同场景下的样式痛点,提供一致的交互体验。

  1. 灵活的功能开关配置

所有扩展功能均支持通过 props 独立开关:可关闭全屏图标、隐藏头部底部分割线、隐藏底部区域、关闭底部顶部分割线,支持自定义标题、最大高度、是否点击遮罩关闭、关闭时是否销毁等所有原生配置,满足新增、编辑、详情、确认等不同业务场景的弹窗需求。

  1. 安全的生命周期与性能优化

使用 computed 缓存弹窗实例方法,watch 立即执行初始化 CSS 变量保证样式首次渲染正确,scrollbar 默认开启 noresize 减少性能消耗,组件卸载时自动随 Vue 生命周期清理事件监听与 watcher,无内存泄漏问题,保证在动态渲染、频繁开关弹窗场景下的稳定性。

使用

UseElDialog

Props

ts
/**
 * 组件props
 */
export default {
  /**
   * el-dialog的标题
   */
  title: {
    type: String,
    default: ''
  },
  /**
   * el-dialog自身是否插入至body元素上。嵌套的el-dialog必须指定该属性并赋值为 true 默认是
   */
  appendToBody: {
    type: Boolean,
    default: true
  },
  /**
   * el-dialog CSS 中的 margin-top 值 默认12dvh
   */
  top: {
    type: String,
    default: '12dvh'
  },
  /**
   * el-dialog内容区域最大高度 默认为autoMax,内部自动根据浏览器高度进行计算最大高度
   */
  maxHeight: {
    type: [String, Number],
    default: 'autoCalcMaxHeight'
  },
  /**
   * el-scrollbar不响应容器尺寸变化,如果容器尺寸不会发生变化,最好设置它可以优化性能
   */
  noresize: {
    type: Boolean,
    default: true
  },
  /**
   * 是否可以通过点击modal关闭el-dialog 默认否
   */
  closeOnClickModal: {
    type: Boolean,
    default: false
  },
  /**
   * 控制是否在关闭el-dialog后将子元素全部销毁 默认是
   */
  destroyOnClose: {
    type: Boolean,
    default: true
  },
  /**
   * 是否显示全屏图标 默认是
   */
  showFullScreenIcon: {
    type: Boolean,
    default: true
  },
  /**
   * 是否显示header底部border 默认是
   */
  showHeaderBottomBorder: {
    type: Boolean,
    default: true
  },
  /**
   * 是否显示footer 默认显示,可通过<template #footer></template>插槽自定义footer内容
   */
  showFooter: {
    type: Boolean,
    default: true
  },
  /**
   * 是否显示footer顶部border 默认否
   */
  showFooterTopBorder: {
    type: Boolean,
    default: false
  },
  /**
   * 底部定位 默认left
   */
  footerPosition: {
    type: String,
    default: 'left',
    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: '取消'
  },
  /**
   * 确定按钮loading状态
   */
  confirmLoading: {
    type: Boolean,
    default: false
  },
  /**
   * 取消按钮类型
   */
  cancelBtnType: {
    type: String,
    default: '',
    validator: (val: string) =>
      [
        '',
        'default',
        'primary',
        'success',
        'warning',
        'danger',
        'info'
      ].includes(val)
  },
  /**
   * 确定按钮事件
   */
  onConfirm: {
    type: Function,
    default: () => {}
  },
  /**
   * 取消按钮事件
   */
  onCancel: {
    type: Function,
    default: () => {}
  }
}

Types

ts
import type { ExtractPropTypes } from 'vue'
import componentProps from './props'

/**
 * props类型
 */
export type Props = ExtractPropTypes<typeof componentProps>

Expose

js
defineExpose({ edRef, handleClose })

基于 MIT 许可发布