@iswangh/element-plus-kit-dialog
v0.1.0
Published
Element Plus Kit Dialog 组件包
Readme
@iswangh/element-plus-kit-dialog
Element Plus Kit Dialog 组件,基于 Element Plus Dialog 的封装组件,提供组合式函数 useDialog,支持完全独立使用,无需在模板中添加组件。
📦 安装
npm install @iswangh/element-plus-kit-dialog注意:此包依赖 vue 和 element-plus,安装时会自动安装。
🚀 快速开始
基础用法
useDialog 组合式函数(完全独立使用,无需模板组件):
<script setup lang="ts">
import { useDialog } from '@iswangh/element-plus-kit-dialog'
const dialog = useDialog()
const { modelValue } = dialog.use({
title: '基础弹窗',
content: '这是弹窗内容',
})
// 打开弹窗(弹窗会自动渲染到 DOM,无需在模板中添加组件)
function handleOpen() {
modelValue.value = true
}
</script>
<template>
<el-button @click="handleOpen">打开弹窗</el-button>
<!-- 注意:无需添加任何组件,useDialog 会自动渲染弹窗 -->
</template>引入样式
重要说明:useDialog 已按需导入了 Element Plus Dialog 组件样式,用户导入时样式会自动导入,无需额外配置。
自动导入(默认,推荐)
直接导入即可,样式会自动导入:
import { useDialog } from '@iswangh/element-plus-kit-dialog'单独导入样式(可选)
如果需要在 CSS 文件中单独导入样式,可以使用:
import '@iswangh/element-plus-kit-dialog/style.css'📖 API 文档
useDialog 组合式函数
useDialog(globalConfig?)
创建弹窗实例管理器,支持全局配置。
参数:
globalConfig(可选):页面级别的全局配置,会被所有dialog.use()创建的实例继承
返回值:
UseDialogReturn:包含use方法的对象
示例:
import { useDialog } from '@iswangh/element-plus-kit-dialog'
import { h, ref } from 'vue'
// 创建带全局配置的 dialog 实例
const dialog = useDialog({
width: '600px',
closeOnClickModal: false,
destroyOnClose: true,
scrollbarProps: {
maxHeight: '400px',
},
loadingProps: {
text: '加载中...',
},
})
// 创建弹窗实例
const { modelValue, loading, buttonLoadings, confirmLoading, cancelLoading } = dialog.use({
title: '编辑用户',
content: () => h('div', '弹窗内容'),
// 或者使用 slots
slots: {
default: () => h('div', '弹窗内容'),
header: () => h('div', '自定义头部'),
footer: () => h('div', '自定义底部'),
},
})
// 控制弹窗显示/隐藏
modelValue.value = true
// 控制弹窗 loading
loading.value = true
// 控制按钮 loading(方式1:使用 buttonLoadings)
buttonLoadings.value.confirm = true
// 控制按钮 loading(方式2:使用快捷方式)
confirmLoading.value = true
cancelLoading.value = truedialog.use(options)
创建弹窗实例。
参数:
options:Dialog 选项,会继承useDialog()传入的全局配置
返回值:
DialogInstance:弹窗实例,包含modelValue、loading、buttonLoadings等响应式状态
DialogOptions:
支持 ElDialog 所有的属性(包括 beforeClose、@opened、@closed 等生命周期钩子)。
拓展属性:
content:内容(支持字符串、VNode、组件、渲染函数)- 字符串:直接显示文本内容
- VNode:Vue 虚拟节点
- Component:Vue 组件
- 渲染函数:
() => string | Component | VNode,通过闭包访问响应式状态
scrollbarProps:el-scrollbar 的属性配置(Partial)- 常用属性:
maxHeight(最大高度)、height(固定高度)等 - el-scrollbar 始终内置使用,提供统一的滚动体验
- 常用属性:
loadingProps:el-loading 的属性配置(Partial)- 常用属性:
text(加载文本)、spinner(自定义加载图标)、background(遮罩背景色)等 - 不设置默认值,保持与 el-loading 原生行为一致
- 常用属性:
slots:插槽(header、footer、title、default)- 所有插槽函数通过闭包访问响应式状态,不接收
instance参数 slots.default优先级高于content属性
- 所有插槽函数通过闭包访问响应式状态,不接收
onConfirm:确认按钮钩子(可选)onCancel:取消按钮钩子(可选)loading:弹窗 loading 状态(Ref,可选)- 如果传入则使用用户的,否则使用内部的
- 弹窗 loading 只作用在弹窗内容区域,不是整个弹窗
buttonLoadings:按钮 loading 状态(Ref<Record<string, boolean>>,可选)- 如果传入则使用用户的,否则使用内部的
- 键名对应按钮的 eventName(如 'confirm'、'cancel' 等)
注意:
- 生命周期钩子(
beforeClose、@opened、@closed)直接使用ElDialog的原生支持,无需额外定义 @opened和@closed事件不接收instance参数,通过闭包访问响应式状态content和slots的渲染函数通过闭包访问(从dialog.use()解构的变量),不接收instance参数
DialogInstance:
id:唯一标识符(string)modelValue:v-model 绑定的响应式值(Ref),唯一控制方式- 直接设置
modelValue.value = true/false即可控制弹窗显示/隐藏 - 使用
modelValue命名,符合 Vue 3 v-model 标准和 Element Plus 规范
- 直接设置
loading:弹窗加载状态(Ref),自动显示遮罩层- 弹窗 loading 只作用在弹窗内容区域,不是整个弹窗
- 通过
instance.loading.value = true/false控制
buttonLoadings:统一的按钮 loading 管理(Ref<Record<string, boolean>>)- 键名对应按钮的 eventName(如 'confirm'、'cancel'、'draft' 等)
- 直接使用
buttonLoadings.value.buttonName = true/false即可
confirmLoading:确认按钮 loading(WritableComputedRef),快捷方式- 等同于
buttonLoadings.value.confirm - 可以直接设置
confirmLoading.value = true/false
- 等同于
cancelLoading:取消按钮 loading(WritableComputedRef),快捷方式- 等同于
buttonLoadings.value.cancel - 可以直接设置
cancelLoading.value = true/false
- 等同于
💡 使用建议
核心特性:
- ✅
useDialog完全独立使用,通过createDialogApp自动创建和挂载 Vue 应用,弹窗自动渲染到 DOM,无需在模板中添加任何组件 - ✅ 只使用
v-model控制弹窗显示/隐藏(modelValue.value = true/false) - ✅ 支持
ElDialog的原生生命周期钩子(beforeClose、@opened、@closed),支持异步 - ✅ 内置 loading 状态管理(弹窗和按钮级别)
- 弹窗 loading:通过
instance.loading.value = true/false控制,自动显示遮罩层 - 按钮 loading:通过
instance.buttonLoadings.value.buttonName = true/false或instance.confirmLoading.value = true/false控制
- 弹窗 loading:通过
- ✅ 支持多个弹窗实例,自动管理 z-index(通过 DialogStack 自动分配和更新)
- ✅ 完全透传 Element Plus Dialog 的所有属性、事件、插槽
- ✅ 内置 el-scrollbar,提供统一的滚动体验,支持
scrollbarProps自定义配置 - ✅ 支持
loadingProps自定义 el-loading 配置,保持与 el-loading 原生行为一致
数据共享模式:
- 所有插槽函数和
content渲染函数通过闭包访问响应式状态 - 在
onOpened中获取的数据可以通过响应式变量在default、header、footer等插槽中共享使用 - 自定义组件可以通过 props 传递数据,通过事件监听处理组件暴露的事件
📚 更多示例
基础示例
import { useDialog } from '@iswangh/element-plus-kit-dialog'
import { ElButton, ElMessage } from 'element-plus'
const dialog = useDialog()
const { modelValue, loading } = dialog.use({
title: '基础弹窗',
width: '500px',
content: '这是弹窗内容',
onOpened: async () => {
loading.value = true
// 模拟异步操作
await new Promise(resolve => setTimeout(resolve, 2000))
loading.value = false
ElMessage.success('数据加载完成')
},
})使用插槽
import { useDialog } from '@iswangh/element-plus-kit-dialog'
import { ElButton, ElMessage } from 'element-plus'
import { h } from 'vue'
const dialog = useDialog()
const { modelValue, confirmLoading, cancelLoading } = dialog.use({
width: '500px',
slots: {
header: () => h('div', { style: { fontWeight: 'bold' } }, '自定义头部'),
default: () => h('div', '这是弹窗内容区域'),
footer: () => h('div', { style: { textAlign: 'right' } }, [
h(ElButton, {
loading: cancelLoading.value,
onClick: () => {
modelValue.value = false
},
}, () => '取消'),
h(ElButton, {
type: 'primary',
loading: confirmLoading.value,
onClick: async () => {
confirmLoading.value = true
await new Promise(resolve => setTimeout(resolve, 2000))
confirmLoading.value = false
ElMessage.success('操作完成')
modelValue.value = false
},
}, () => '确认'),
]),
},
})数据共享示例
import { useDialog } from '@iswangh/element-plus-kit-dialog'
import { ElButton, ElMessage } from 'element-plus'
import { h, ref } from 'vue'
const dialog = useDialog()
// 在 onOpened 中获取的数据可以通过响应式变量在插槽中共享使用
const userData = ref<{ username: string, email: string } | null>(null)
const { modelValue, loading } = dialog.use({
title: '数据共享示例',
width: '600px',
slots: {
default: () => {
// 在 default 插槽中访问 onOpened 中获取的数据(通过闭包访问)
if (!userData.value) {
return h('div', '数据加载中...')
}
return h('div', [
h('p', `用户名: ${userData.value.username}`),
h('p', `邮箱: ${userData.value.email}`),
])
},
},
onOpened: async () => {
loading.value = true
// 模拟异步请求
await new Promise(resolve => setTimeout(resolve, 2000))
userData.value = {
username: 'John Doe',
email: '[email protected]',
}
loading.value = false
ElMessage.success('数据加载完成')
},
onClosed: () => {
// 清理数据
userData.value = null
},
})scrollbarProps 和 loadingProps 配置
import { useDialog } from '@iswangh/element-plus-kit-dialog'
import { h } from 'vue'
const dialog = useDialog()
const { modelValue, loading } = dialog.use({
title: '滚动和 Loading 配置',
width: '500px',
scrollbarProps: {
maxHeight: '300px',
},
loadingProps: {
text: '正在加载数据...',
background: 'rgba(0, 0, 0, 0.7)',
},
slots: {
default: () => h('div', Array.from({ length: 20 }, (_, i) =>
h('p', `这是第 ${i + 1} 行内容,用于测试滚动功能。`)
)),
},
})
// 控制 loading
loading.value = true🔗 相关链接
📄 许可证
Apache-2.0
