对话框 Dialog
弹出对话框时,对话框就会被弹出。
基础使用
visible 控制对话框的展示和隐藏,传入 visible 进入受控模式。不传或者为 undefined 则为非受控模式,此时可以传入 defaultVisible 属性作为默认值。
<template>
<div>
<px-dialog title="Title" v-model:visible="visible">
Content Content Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content Content
</px-dialog>
<px-dialog title="Uncontrolled Dialog" ref="dialog">
Content Content Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content Content
</px-dialog>
<px-space>
<px-button @click="visible = true">Open Controlled Dialog</px-button>
<px-button @click="dialog?.open()">Open Uncontrolled Dialog</px-button>
</px-space>
</div>
</template>
<script setup lang="ts">
import { ref, shallowRef } from 'vue'
import { Dialog } from '@pixelium/web-vue'
// If on-demand import
// import { Dialog } from '@pixelium/web-vue/es';
const visible = ref(false)
const dialog = shallowRef<InstanceType<typeof Dialog> | null>(null)
</script>弹窗表单
只是一个对话框中使用表单的栗子🌰。就像栗子所展示的那样,你可以直接传入 class 和 style 等 attrs 穿透到对话框容器元素上。
<template>
<div>
<px-dialog
title="Form"
v-model:visible="visible"
style="max-height: 70vh; width: 600px"
@before-ok="submitHandler"
>
<px-form
:model="form"
:rules="rules"
style="width: 500px"
@submit="submitHandler"
ref="formRef"
poll-size-change
>
<px-form-item label="Input" field="input">
<px-input v-model="form.input" placeholder="Please input..."></px-input>
</px-form-item>
<px-form-item label="Radio" field="radio">
<px-radio-group
v-model="form.radio"
:options="radioOptions"
variant="retro"
></px-radio-group>
</px-form-item>
<px-form-item label="Checkbox" field="checkbox">
<px-checkbox-group
v-model="form.checkbox"
:options="checkboxOptions"
></px-checkbox-group>
</px-form-item>
<px-form-item label="Number" field="number">
<px-input-number
v-model="form.number"
placeholder="Please input..."
></px-input-number>
</px-form-item>
<px-form-item label="Tags" field="tags">
<px-input-tag
v-model="form.tags"
placeholder="Press enter to confirm..."
></px-input-tag>
</px-form-item>
<px-form-item label="Text" field="text">
<px-textarea v-model="form.text" placeholder="Please input text..."></px-textarea>
</px-form-item>
<px-form-item label="Switch" field="switch">
<px-switch v-model="form.switch"></px-switch>
</px-form-item>
<px-form-item label="Select" field="select">
<px-select
:options="options"
v-model="form.select"
placeholder="Please select..."
></px-select>
</px-form-item>
<px-form-item label="Email" field="email">
<px-input v-model="form.email" placeholder="Please email..."></px-input>
</px-form-item>
<px-form-item label="URL" field="url">
<px-input v-model="form.url" placeholder="Please URL..."></px-input>
</px-form-item>
<px-form-item label="Slider" field="slider">
<px-slider v-model="form.slider"></px-slider>
</px-form-item>
<px-form-item label="Number String" field="numberString">
<px-input v-model="form.numberString" placeholder="Please number..."></px-input>
</px-form-item>
</px-form>
</px-dialog>
<px-button @click="visible = true" variant="plain">Open Form Dialog</px-button>
</div>
</template>
<script setup lang="ts">
import { ref, shallowRef } from 'vue'
import { Form } from '@pixelium/web-vue'
// If on-demand import
// import { Form } from '@pixelium/web-vue/es'
const visible = ref(false)
const form = ref({
input: '',
number: 0,
tags: [] as string[],
text: '',
select: null as null | string,
email: '',
url: '',
numberString: '',
switch: false,
radio: null as null | string,
checkbox: [] as string[],
slider: 10
})
const rules = {
input: { required: true, message: 'Please input' },
select: { required: true, message: 'Please select' },
switch: { required: true, message: 'Please select' },
number: { min: 10, message: 'Min is 10' },
tags: [
{ required: true, message: 'Please input tags' },
{ maxLength: 5, message: 'Length less than or equal 5' }
],
text: { required: true, message: 'Just a tip', level: 'warning' },
email: { required: true, email: true, message: 'Please input email' },
url: { required: true, url: true, message: 'Please input a URL' },
numberString: { required: true, numberString: true, message: 'Please input number' },
radio: {
required: true,
validator(value: string) {
return value !== 'Yes' ? 'Please select Yes' : undefined
}
},
checkbox: [
{ required: true, message: 'Please select' },
{ maxLength: 2, message: 'You can select up to 2 items' }
],
slider: { max: 90, message: 'Max is 90' }
}
const options = ref(['vue', 'react', 'angular'])
const radioOptions = ref(['Yes', 'No'])
const checkboxOptions = ref(['A', 'B', 'C', 'D'])
const formRef = shallowRef<null | InstanceType<typeof Form>>(null)
const submitHandler = () => {
return formRef.value?.validate().then(({ isValid }) => {
if (isValid) {
console.log('submit')
return true
} else {
return false
}
})
}
</script>函数式
如果你完整注册了组件库,你可以以以下方式使用它:
window.$dialog;- Vue 组件内:
getCurrentInstance().appContext.config.globalProperties.PixeliumVue.dialog; - 从
@pixelium/web-vue中导入。
按需引入时,也可以从 @pixelium/web-vue/es 中导入 Dialog 使用。
<template>
<px-space>
<px-button @click="info" variant="outline">Info</px-button>
<px-button @click="notice" theme="notice" variant="outline">Notice</px-button>
<px-button @click="success" theme="success" variant="outline">Success</px-button>
<px-button @click="warning" theme="warning" variant="outline">Warning</px-button>
<px-button @click="error" theme="danger" variant="outline">Error</px-button>
<px-button @click="confirm" theme="info" variant="outline">Confirm</px-button>
</px-space>
</template>
<script setup lang="ts">
const info = () => {
$dialog.info('This is an informational dialog.')
}
const notice = () => {
$dialog.notice('This is an notice dialog.')
}
const success = () => {
$dialog.success('This is a success dialog.')
}
const warning = () => {
$dialog.warning('This is a warning dialog.')
}
const error = () => {
$dialog.error('This is an error dialog.')
}
const confirm = () => {
$dialog.confirm('Are you sure to proceed?').then((ok) => {
if (ok) {
$dialog.success('You have confirmed.')
} else {
$dialog.info('You have cancelled.')
}
})
}
</script>异步确认
传入 onBeforeOk 后,在确认时将会等待 onBeforeOk 执行完成,若结果不为 false 再执行后续代码。
<template>
<px-space>
<px-button @click="confirm" theme="warning">Async Confirm</px-button>
</px-space>
</template>
<script setup lang="ts">
const confirm = () => {
$dialog
.confirm({
title: 'Async Confirm',
content: 'Are you sure to proceed with async operation?',
onBeforeOk() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(Math.random() > 0.5)
}, 2000)
})
},
okText: 'Random Succeed',
cancelText: 'Cancel',
okButtonProps: {
theme: 'warning'
}
})
.then((ok) => {
if (ok) {
$message.success('You have confirmed.')
} else {
$message.info('You have cancelled.')
}
})
}
</script>API
Dialog Function
Dialog 上的函数调用后,返回一个 Promise<boolean>,通过确认关闭弹窗,则以 true fulfilled,否则为 false。
ts
type DialogReturn = Promise<boolean> & {
close: () => void
}
// ...
{
[key in DialogOptions['type'] & string]: (
options:
| (Omit<DialogOptions, 'type'> & Omit<EmitEvent<DialogEvents>, 'update:visible'>)
| string
) => DialogReturn
}就像上面栗子所展示的那样🌰,作为组件时你可以直接传入 class 和 style 等 attrs 穿透到对话框容器元素上。
DialogOptions
| 属性 | 类型 | 可选 | 默认值 | 描述 | 版本 |
|---|---|---|---|---|---|
| content | ValidContent | 否 | | 对话框内容。 | 0.1.0 |
| title | ValidContent | 是 | | 对话框标题。 | 0.1.0 |
| icon | ValidVNodeContent | 是 | | 对话框标题图标。 | 0.1.0 |
| footer | ValidVNodeContent | 是 | | 对话框底部区域。 | 0.1.0 |
| type | 'info' | 'success' | 'warning' | 'error' | 'normal' | 'confirm' | 'notice' | 是 | 'normal' | 对话框类型。 | 0.1.0 |
| closable | boolean | 是 | true | 是否展示右上角关闭按钮。 | 0.1.0 |
| mask | boolean | 是 | true | 是否展示遮罩层。 | 0.1.0 |
| maskClosable | boolean | 是 | true | 点击遮罩层是否可以关闭对话框。 | 0.1.0 |
| escToClose | boolean | 是 | true | 是否可以按 ESC 键关闭对话框,需要聚焦到对话框中。 | 0.1.0 |
| showCancel | boolean | 是 | | 是否展示取消按钮,不设置时,受 type 字段影响,仅 'confirm' 时展示。 | 0.1.0 |
| okText | string | 是 | | 确认按钮文本内容。 | 0.1.0 |
| cancelText | string | 是 | | 取消按钮文本内容。 | 0.1.0 |
| showFooter | boolean | 是 | true | 是否展示对话框底部区域。 | 0.1.0 |
| zIndex | number | 是 | | 对话框的 z-index 属性。 | 0.1.0 |
| root | string | HTMLElement | 是 | 'body' | 对话框挂载的根元素。 | 0.1.0 |
| okButtonProps | ButtonProps & EmitEvent<ButtonEvents> & RestAttrs | 是 | | 确认按钮的属性。 | 0.1.0 |
| cancelButtonProps | ButtonProps & EmitEvent<ButtonEvents> & RestAttrs | 是 | | 取消按钮的属性。 | 0.1.0 |
| maskProps | Omit<MaskProps, 'zIndex'> | 是 | | 遮罩层的属性。 | 0.1.0 |
| containerProps | RestAttrs | 是 | | 对话框容器元素的属性。 | 0.1.0 |
| headerProps | RestAttrs | 是 | | 对话框头部区域元素的属性。 | 0.1.0 |
| bodyProps | RestAttrs | 是 | | 对话框内容区域元素的属性。 | 0.1.0 |
| footerProps | RestAttrs | 是 | | 对话框底部区域元素的属性。 | 0.1.0 |
DialogProps
| 属性 | 类型 | 可选 | 默认值 | 描述 | 版本 |
|---|---|---|---|---|---|
| visible | boolean | null | 是 | | 控制对话框展示,受控模式,支持 v-model。 | 0.1.0 |
| visible | boolean | null | 是 | | 控制对话框展示,受控模式,支持 v-model。 | 0.1.0 |
| title | string | 是 | '' | 对话框标题。 | 0.1.0 |
| closable | boolean | 是 | true | 是否展示右上角关闭按钮。 | 0.1.0 |
| mask | boolean | 是 | true | 是否展示遮罩层。 | 0.1.0 |
| maskClosable | boolean | 是 | true | 点击遮罩层是否可以关闭对话框。 | 0.1.0 |
| escToClose | boolean | 是 | true | 是否可以按 ESC 键关闭对话框,需要聚焦到对话框中。 | 0.1.0 |
| showCancel | boolean | 是 | true | 是否展示取消按钮,不设置时,受 type 字段影响,仅 'confirm' 时展示。 | 0.1.0 |
| okText | string | 是 | | 确认按钮文本内容。 | 0.1.0 |
| cancelText | string | 是 | | 取消按钮文本内容。 | 0.1.0 |
| boolean | boolean | 是 | false | 0.1.0 | |
| showFooter | boolean | 是 | true | 是否展示对话框底部区域。 | 0.1.0 |
| root | string | HTMLElement | 是 | 'body' | 对话框挂载的根元素。 | 0.1.0 |
| zIndex | number | 是 | | 对话框的 z-index 属性。 | 0.1.0 |
| destroyOnHide | boolean | 是 | false | 对话框内容是否在隐藏后销毁。 | 0.1.0 |
| okButtonProps | ButtonProps & EmitEvent<ButtonEvents> & RestAttrs | 是 | | 确认按钮的属性。 | 0.1.0 |
| cancelButtonProps | ButtonProps & EmitEvent<ButtonEvents> & RestAttrs | 是 | | 取消按钮的属性。 | 0.1.0 |
| maskProps | Omit<MaskProps, 'zIndex'> | 是 | | 遮罩层的属性。 | 0.1.0 |
| containerProps | RestAttrs | 是 | | 对话框容器元素的属性。 | 0.1.0 |
| headerProps | RestAttrs | 是 | | 对话框头部区域元素的属性。 | 0.1.0 |
| bodyProps | RestAttrs | 是 | | 对话框内容区域元素的属性。 | 0.1.0 |
| footerProps | RestAttrs | 是 | | 对话框底部区域元素的属性。 | 0.1.0 |
DialogSlots
| 插槽 | 参数 | 描述 | 版本 |
|---|---|---|---|
| default | | 对话框内容。 | 0.1.0 |
| title | | 对话框标题。 | 0.1.0 |
| icon | | 对话框标题图标。 | 0.1.0 |
| footer | | 对话框底部区域。 | 0.1.0 |
DialogEvents
| 事件 | 参数 | 描述 | 版本 |
|---|---|---|---|
| update:visible | | 用于更新受控模式的 visible 值。 | 0.1.0 |
| beforeOk | | 用于异步确认,需返回一个 Promise<boolean | void> | boolean | void 类型的数据判断是否成功,await 操作后不为 false 即为确认成功。 | 0.1.0 |
| ok | event: MouseEvent | 通过确认成功关闭弹窗的回调。 | 0.1.0 |
| cancel | event: MouseEvent | KeyboardEvent | 通过取消、关闭按钮、遮罩层、ESC 键等方法,关闭弹窗的回调。 | 0.1.0 |
| open | | 弹窗打开时的回调。 | 0.1.0 |
| afterOpen | | 弹窗打开动画结束后的回调。 | 0.1.0 |
| close | | 弹窗关闭时的回调。 | 0.1.0 |
| afterClose | | 弹窗关闭动画结束后的回调。 | 0.1.0 |
DialogExpose
| 属性 | 类型 | 可选 | 默认值 | 描述 | 版本 |
|---|---|---|---|---|---|
| close | () => void | 否 | | 关闭弹窗。 | 0.1.0 |
| open | () => void | 否 | | 打开弹窗。 | 0.1.0 |
ValidContent, ValidVNodeContent
ts
export type ValidContent = string | ((...args: any[]) => VNode | string | JSX.Element | null | void)
export type ValidVNodeContent = (...args: any[]) => VNode | JSX.ElementRestAttrs
ts
import type { StyleValue } from 'vue'
export type VueClassValue = string | Record<string, any> | VueClassValue[]
export type VueStyleValue = StyleValue
export type RestAttrs = {
style?: VueStyleValue | null
class?: VueClassValue | null
[x: string]: any
}EmitEvent
ts
export type EmitEvent<T extends Record<string, any>> = {
[K in keyof T as `on${Capitalize<K & string>}`]?: (...args: T[K]) => void
}