Dialog 对话框
在保留当前页面状态的情况下,告知用户并承载相关操作。
基础用法
Dialog 弹出一个对话框,适合需要定制性更大的场景。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">打开对话框</ExButton>
<ExDialog v-model="dialogVisible" title="提示">
<p>这是一段信息</p>
<p>这是另一段信息</p>
</ExDialog>
</template>
<script setup>
import { ref } from 'vue';
const dialogVisible = ref(false);
</script>自定义标题
通过 title 插槽可以自定义标题内容。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">自定义标题</ExButton>
<ExDialog v-model="dialogVisible">
<template #title>
<span style="color: var(--ex-color-neon-blue-500);"> 🎮 游戏设置 </span>
</template>
<template #icon>
<img
src="https://api.iconify.design/ri/settings-3-line.svg"
alt="设置"
width="24"
height="24"
/>
</template>
<div>画质:超高</div>
<div>帧率:144 FPS</div>
</ExDialog>
</template>不同类型
通过 type 属性可以设置不同类型的对话框。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">主要对话框</ExButton>
<ExDialog v-model="dialogVisible" title="主要对话框" type="primary">
<template #icon>
<img
src="https://api.iconify.design/ri/information-line.svg"
alt="信息"
width="24"
height="24"
/>
</template>
<p>这是一个主要类型的对话框。</p>
</ExDialog>
</template>不同尺寸
通过 size 属性可以设置不同尺寸的对话框。
vue
<template>
<ExButton @click="dialogVisible = true">小尺寸</ExButton>
<ExDialog v-model="dialogVisible" title="小尺寸对话框" size="small">
<p>这是一个小尺寸的对话框。</p>
</ExDialog>
</template>自定义底部
通过 footer 插槽可以自定义底部内容。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">自定义底部</ExButton>
<ExDialog
v-model="dialogVisible"
title="确认操作"
:confirm-loading="confirmLoading"
@confirm="handleConfirm"
>
<p>您确定要执行此操作吗?</p>
</ExDialog>
</template>
<script setup>
import { ref } from 'vue';
const dialogVisible = ref(false);
const confirmLoading = ref(false);
const handleConfirm = () => {
confirmLoading.value = true;
setTimeout(() => {
confirmLoading.value = false;
dialogVisible.value = false;
}, 2000);
};
</script>居中显示
设置 center 属性可以让对话框内容居中显示。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">居中对话框</ExButton>
<ExDialog v-model="dialogVisible" title="居中显示" center>
<div style="text-align: center;">
<div style="font-size: 48px;">🏆</div>
<div>恭喜获胜!</div>
</div>
</ExDialog>
</template>全屏对话框
设置 fullscreen 属性可以让对话框全屏显示。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">全屏对话框</ExButton>
<ExDialog v-model="dialogVisible" title="全屏对话框" fullscreen>
<div>全屏内容</div>
</ExDialog>
</template>嵌套对话框
对话框可以嵌套使用。
vue
<template>
<ExButton type="primary" @click="outerVisible = true">打开外层对话框</ExButton>
<ExDialog v-model="outerVisible" title="外层对话框">
<p>这是外层对话框的内容。</p>
<ExButton type="primary" @click="innerVisible = true">打开内层对话框</ExButton>
<ExDialog v-model="innerVisible" title="内层对话框" :z-index="1060">
<p>这是内层对话框的内容。</p>
</ExDialog>
</ExDialog>
</template>
<script setup>
import { ref } from 'vue';
const outerVisible = ref(false);
const innerVisible = ref(false);
</script>自定义关闭按钮
通过 close 插槽可以自定义关闭按钮。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">自定义关闭按钮</ExButton>
<ExDialog v-model="dialogVisible" title="自定义关闭">
<template #close>
<img
src="https://api.iconify.design/ri/close-circle-line.svg"
alt="关闭"
width="20"
height="20"
/>
</template>
<p>自定义关闭按钮</p>
</ExDialog>
</template>不显示底部
设置 :show-footer="false" 可以隐藏底部操作栏。
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">无底部对话框</ExButton>
<ExDialog v-model="dialogVisible" title="纯内容展示" :show-footer="false">
<p>这是一个纯内容展示的对话框。</p>
</ExDialog>
</template>关闭前回调
通过 before-close 属性可以在关闭前执行回调,返回 false 可以阻止关闭。
当前状态: 有未保存内容(阻止关闭)
vue
<template>
<ExButton type="primary" @click="dialogVisible = true">打开对话框</ExButton>
<ExDialog v-model="dialogVisible" title="编辑内容" :before-close="handleBeforeClose">
<p>尝试关闭对话框,如果有未保存内容会被阻止。</p>
</ExDialog>
</template>
<script setup>
import { ref } from 'vue';
const dialogVisible = ref(false);
const hasUnsavedChanges = ref(true);
const handleBeforeClose = async () => {
// 如果有未保存的更改,阻止关闭
if (hasUnsavedChanges.value) {
console.log('有未保存的内容,阻止关闭');
return false;
}
return true;
};
</script>API
Dialog Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
model-value / v-model | 是否显示对话框 | boolean | false |
title | 对话框标题 | string | '' |
size | 对话框尺寸 | 'small' | 'medium' | 'large' | 'full' | 'medium' |
type | 对话框类型 | 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'default' |
show-close | 是否显示关闭按钮 | boolean | true |
modal | 是否显示遮罩层 | boolean | true |
close-on-click-modal | 是否可以通过点击遮罩层关闭 | boolean | true |
close-on-press-escape | 是否可以通过按下 ESC 键关闭 | boolean | true |
show-footer | 是否显示底部操作栏 | boolean | true |
confirm-text | 确认按钮文本 | string | '确认' |
cancel-text | 取消按钮文本 | string | '取消' |
show-confirm | 是否显示确认按钮 | boolean | true |
show-cancel | 是否显示取消按钮 | boolean | true |
confirm-loading | 确认按钮加载状态 | boolean | false |
confirm-disabled | 确认按钮禁用状态 | boolean | false |
center | 是否居中显示 | boolean | false |
fullscreen | 是否全屏显示 | boolean | false |
lock-scroll | 是否锁定滚动 | boolean | true |
custom-class | 自定义类名 | string | '' |
modal-class | 遮罩层自定义类名 | string | '' |
before-open | 对话框打开前的回调 | () => boolean | Promise<boolean> | undefined |
before-close | 对话框关闭前的回调 | () => boolean | Promise<boolean> | undefined |
z-index | 层级 | number | 1050 |
append-to-body | 是否追加到 body | boolean | true |
destroy-on-close | 是否在关闭时销毁内容 | boolean | false |
aria-label | 无障碍标签 | string | undefined |
Dialog Events
| 事件名 | 说明 | 类型 |
|---|---|---|
update:model-value | 更新 modelValue | (value: boolean) => void |
open | 对话框打开时触发 | () => void |
opened | 对话框打开动画结束时触发 | () => void |
close | 对话框关闭时触发 | () => void |
closed | 对话框关闭动画结束时触发 | () => void |
confirm | 点击确认按钮时触发 | () => void |
cancel | 点击取消按钮时触发 | () => void |
Dialog Slots
| 插槽名 | 说明 |
|---|---|
default | 对话框内容 |
title | 自定义标题 |
icon | 自定义图标 |
close | 自定义关闭按钮 |
footer | 自定义底部内容 |
Dialog Methods
| 方法名 | 说明 | 类型 |
|---|---|---|
open | 打开对话框 | () => void |
close | 关闭对话框 | () => void |
getElement | 获取对话框 DOM 元素 | () => HTMLDivElement | null |
无障碍支持
- 使用
role="dialog"和aria-modal属性 - 支持 ESC 键关闭
- 完整的 ARIA 标签支持
- 支持屏幕阅读器
- 自动锁定焦点在对话框内
主题定制
可以通过 CSS 变量自定义对话框样式:
css
:root {
--ex-dialog-bg: var(--ex-color-bg-surface);
--ex-dialog-border-color: var(--ex-color-border-primary);
--ex-dialog-shadow: var(--ex-shadow-2xl);
--ex-dialog-header-border: var(--ex-color-border-primary);
--ex-dialog-footer-border: var(--ex-color-border-primary);
}