Dialog 对话框
用于承载需要用户聚焦处理的确认、编辑或详情内容。
基础用法
vue
<template>
<x-button type="primary" @click="visible = true">打开对话框</x-button>
<x-dialog v-model="visible" title="标题" width="520px">
内容
<template #footer="{ cancel, ok, loadingObj }">
<x-space>
<x-button :loading="loadingObj.cancel" @click="cancel">取消</x-button>
<x-button type="primary" :loading="loadingObj.ok" @click="ok">确认</x-button>
</x-space>
</template>
</x-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const visible = ref(false);
</script>异步关闭
vue
<template>
<x-button type="primary" @click="visible = true">异步确认</x-button>
<x-dialog v-model="visible" title="提交确认" :on-before-cancel="beforeClose">
确认按钮会等待异步任务完成;取消按钮会被拦截并保持打开。
<template #footer="{ cancel, ok, loadingObj }">
<x-space>
<x-button :loading="loadingObj.cancel" @click="cancel">取消</x-button>
<x-button type="primary" :loading="loadingObj.ok" @click="ok">提交</x-button>
</x-space>
</template>
</x-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const visible = ref(false);
const beforeClose = async (action: 'cancel' | 'ok') => {
if (action === 'cancel') return false;
await new Promise((resolve) => window.setTimeout(resolve, 1200));
return true;
};
</script>显示方式
vue
<template>
<x-space wrap>
<x-button @click="centerVisible = true">居中</x-button>
<x-button @click="topVisible = true">顶部距离</x-button>
<x-button @click="fullscreenVisible = true">全屏</x-button>
</x-space>
<x-dialog v-model="centerVisible" center title="居中对话框" />
<x-dialog v-model="topVisible" title="自定义顶部距离" top="80px" />
<x-dialog v-model="fullscreenVisible" title="全屏对话框" fullscreen />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const centerVisible = ref(false);
const topVisible = ref(false);
const fullscreenVisible = ref(false);
</script>保留内容状态
vue
<template>
<x-button @click="visible = true">打开并保留内容</x-button>
<x-dialog v-model="visible" title="关闭后保留内容" :destroy-on-closed="false">
<x-input v-model="text" placeholder="关闭后再次打开,内容仍会保留" />
</x-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const visible = ref(false);
const text = ref('');
</script>命令式调用
vue
<template>
<x-space wrap>
<x-button type="primary" @click="openCommandDialog">命令式打开</x-button>
<x-button @click="openNoFooterDialog">无底部按钮</x-button>
<x-button @click="openManualDialog">手动更新关闭</x-button>
<x-button @click="Dialog.destroyAll()">关闭全部</x-button>
</x-space>
</template>
<script setup lang="ts">
import { Dialog } from 'x-next';
const openCommandDialog = () => {
Dialog({
title: '提交确认',
content: '确认提交当前表单吗?',
onOk: () => console.log('ok'),
});
};
const openNoFooterDialog = () => {
Dialog({
title: '说明',
content: () => 'footer=false 时不会显示底部按钮',
footer: false,
});
};
const openManualDialog = () => {
const instance = Dialog({
title: '处理中',
content: '3 秒后关闭',
});
window.setTimeout(() => instance.update({ content: '即将关闭' }), 1500);
window.setTimeout(() => instance.close(), 3000);
};
</script>局部容器
vue
<template>
<x-button @click="openLocalDialog">挂载到局部容器</x-button>
<div id="dialog-local-container" class="dialog-local-container"></div>
</template>
<script setup lang="ts">
import { Dialog } from 'x-next';
const openLocalDialog = () => {
Dialog({
title: '局部容器',
content: 'renderTo 找不到目标时会回退到 body',
renderTo: '#dialog-local-container',
});
};
</script>按需导入
ts
import { Dialog } from 'x-next';Component Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
modelValue | 是否显示对话框 | boolean | false |
renderTo | 挂载容器,找不到时回退到 body | string | HTMLElement | 'body' |
disabled | 是否禁用 Teleport | boolean | false |
top | 距离顶部位置,center=false 时生效 | string | number | '3vh' |
center | 是否居中显示 | boolean | false |
width | 宽度 | string | number | 0 |
height | 高度 | string | number | 0 |
minWidth | 最小宽度 | string | number | 0 |
minHeight | 最小高度 | string | number | 0 |
title | 标题 | string | '' |
mask | 是否显示遮罩 | boolean | true |
maskToClose | 点击遮罩是否关闭 | boolean | true |
escToClose | 按下 Esc 是否关闭 | boolean | true |
fullscreen | 是否全屏 | boolean | false |
destroyOnClosed | 关闭后是否销毁内容 | boolean | true |
onBeforeCancel | 关闭前拦截,返回 false 阻止关闭 | (action?: 'cancel' | 'ok') => boolean | Promise<boolean> | - |
popupClass | 弹层自定义类名 | string | - |
showClose | 是否显示关闭按钮 | boolean | true |
showHeaderBottomLine | 是否显示标题底部分割线 | boolean | false |
hideFooter | 是否隐藏底部区域 | boolean | false |
Component Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
update:modelValue | 显隐状态变化时触发 | value: boolean |
open | 打开时触发 | - |
opened | 打开动画结束后触发 | - |
close | 请求关闭时触发 | action: 'cancel' | 'ok', event?: Event |
closed | 关闭动画结束后触发 | - |
Component Slots
| 插槽名 | 说明 | 参数 |
|---|---|---|
title | 自定义标题 | - |
default | 对话框主体内容 | - |
footer | 自定义底部操作区 | { cancel, ok, loadingObj, loading-obj } |
Dialog Methods
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
Dialog(options) | 打开命令式对话框 | DialogOptions | DialogReturn |
Dialog.destroyAll() | 关闭全部命令式对话框 | - | void |
Dialog Options
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
title | 标题 | DialogContent | - |
content | 正文内容 | DialogContent | - |
footer | 自定义底部;false 时隐藏底部 | boolean | VNode | (scoped) => DialogRenderResult | 默认按钮 |
okText | 确认按钮文案 | string | '确认' |
cancelText | 取消按钮文案 | string | '取消' |
mask | 是否显示遮罩 | boolean | true |
maskToClose | 点击遮罩是否关闭 | boolean | true |
beforeOnOk | 确认前拦截 | () => boolean | Promise<boolean> | - |
beforeOnCancel | 取消前拦截 | () => boolean | Promise<boolean> | - |
onOk | 点击确认回调 | (event: Event) => void | - |
onCancel | 点击取消回调 | (event: Event) => void | - |
width | 宽度 | string | number | 368 |
height | 高度 | string | number | 'auto' |
top | 距离顶部位置 | string | number | 0 |
center | 是否居中 | boolean | true |
renderTo | 挂载容器,找不到时回退到 body | string | HTMLElement | 'body' |
hideCancel | 是否隐藏取消按钮 | boolean | false |
hideOk | 是否隐藏确认按钮 | boolean | false |
popupClass | 弹层自定义类名 | string | - |
返回值
| 方法 | 说明 | 参数 |
|---|---|---|
close() | 关闭当前对话框 | - |
update(options) | 更新当前对话框配置 | Partial<DialogOptions> |
无障碍说明
Dialog 打开后会聚焦到对话框内的首个可聚焦元素,Tab 会在对话框内部循环,关闭后会把焦点恢复到打开前的元素。对话框容器带有 role="dialog" 和标题关联,右上角关闭控件是可聚焦按钮。