Skip to content

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是否显示对话框booleanfalse
renderTo挂载容器,找不到时回退到 bodystring | HTMLElement'body'
disabled是否禁用 Teleportbooleanfalse
top距离顶部位置,center=false 时生效string | number'3vh'
center是否居中显示booleanfalse
width宽度string | number0
height高度string | number0
minWidth最小宽度string | number0
minHeight最小高度string | number0
title标题string''
mask是否显示遮罩booleantrue
maskToClose点击遮罩是否关闭booleantrue
escToClose按下 Esc 是否关闭booleantrue
fullscreen是否全屏booleanfalse
destroyOnClosed关闭后是否销毁内容booleantrue
onBeforeCancel关闭前拦截,返回 false 阻止关闭(action?: 'cancel' | 'ok') => boolean | Promise<boolean>-
popupClass弹层自定义类名string-
showClose是否显示关闭按钮booleantrue
showHeaderBottomLine是否显示标题底部分割线booleanfalse
hideFooter是否隐藏底部区域booleanfalse

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)打开命令式对话框DialogOptionsDialogReturn
Dialog.destroyAll()关闭全部命令式对话框-void

Dialog Options

参数说明类型默认值
title标题DialogContent-
content正文内容DialogContent-
footer自定义底部;false 时隐藏底部boolean | VNode | (scoped) => DialogRenderResult默认按钮
okText确认按钮文案string'确认'
cancelText取消按钮文案string'取消'
mask是否显示遮罩booleantrue
maskToClose点击遮罩是否关闭booleantrue
beforeOnOk确认前拦截() => boolean | Promise<boolean>-
beforeOnCancel取消前拦截() => boolean | Promise<boolean>-
onOk点击确认回调(event: Event) => void-
onCancel点击取消回调(event: Event) => void-
width宽度string | number368
height高度string | number'auto'
top距离顶部位置string | number0
center是否居中booleantrue
renderTo挂载容器,找不到时回退到 bodystring | HTMLElement'body'
hideCancel是否隐藏取消按钮booleanfalse
hideOk是否隐藏确认按钮booleanfalse
popupClass弹层自定义类名string-

返回值

方法说明参数
close()关闭当前对话框-
update(options)更新当前对话框配置Partial<DialogOptions>

无障碍说明

Dialog 打开后会聚焦到对话框内的首个可聚焦元素,Tab 会在对话框内部循环,关闭后会把焦点恢复到打开前的元素。对话框容器带有 role="dialog" 和标题关联,右上角关闭控件是可聚焦按钮。