MessageBox 消息弹框
模拟系统的消息提示框而实现的一套模态对话框组件。
?
| 名称 | 分类 | 说明 | 类型 | 默认值 |
|---|---|---|---|---|
type | ? 风格 | 消息类型 | 'success' | 'warning' | 'info' | 'danger' | 'error' | — |
cancelButtonType | ? 风格 | 取消按钮类型 | ButtonType | — |
confirmButtonType | ? 风格 | 确认按钮类型 | ButtonType | 'primary' |
center | ? 风格 | 是否居中布局 | boolean | false |
inputType | ? 风格 | 输入框类型 | 'text' | 'textarea' | 'password' | 'number' | 'text' |
customClass | ? 风格 | 自定义对话框根元素的类名 | string | — |
customStyle | ? 风格 | 自定义对话框根元素的内联样式 | CSSProperties | — |
width | ? 风格 | 自定义对话框宽度(数字为 px,字符串为 CSS 值) | string | number | 420 |
overlayClass | ? 风格 | 自定义遮罩层的类名 | string | string[] | Record<string, boolean> | — |
showClose | ? 行为 | 是否显示关闭按钮 | boolean | true |
showCancelButton | ? 行为 | 是否显示取消按钮 | boolean | false |
showConfirmButton | ? 行为 | 是否显示确认按钮 | boolean | true |
lockScroll | ? 行为 | 是否锁定滚动 | boolean | true |
closeOnClickModal | ? 行为 | 是否可通过点击遮罩关闭 | boolean | true |
showInput | ? 行为 | 是否显示输入框 | boolean | false |
callback | ? 行为 | 关闭后的回调函数 | (action: MessageBoxAction | { value: string; action: MessageBoxAction }) => void | — |
beforeClose | ? 行为 | 关闭前的回调,调用 done 关闭弹框;若返回 Promise,按钮自动显示加载状态 | (action: MessageBoxAction, instance: MessageBoxOptions, done: () => void) => void | Promise<void> | — |
closeOnPressEscape | ? 行为 | 是否可通过按 Escape 键关闭 | boolean | true |
closeOnHashChange | ? 行为 | 是否在 URL hash 变化时关闭 | boolean | true |
inputSchema | ? 行为 | 输入框的 Zod 验证 schema | ZodType | — |
distinguishCancelAndClose | ? 行为 | 关闭按钮是否触发 "close" 而非 "cancel" | boolean | true |
draggable | ? 行为 | 是否可通过拖拽标题栏移动对话框 | boolean | false |
title | ? 内容 | 标题 | string | — |
message | ? 内容 | 消息内容 | string | VNode | — |
cancelButtonText | ? 内容 | 取消按钮文字 | string | 'No' |
confirmButtonText | ? 内容 | 确认按钮文字 | string | 'Yes' |
inputPlaceholder | ? 内容 | 输入框占位文本 | string | — |
inputValue | ? 内容 | 输入框初始值 | string | — |
inputErrorMessage | ? 内容 | 验证失败时的自定义错误提示 | string | — |
footer | ? 内容 | 自定义底部内容,替换默认按钮 | VNode | (() => VNode) | — |
PxMessageBox | ? 方法 | 打开消息弹框 | (options: MessageBoxOptions) => Promise<MessageBoxData> | — |
PxMessageBox.alert | ? 方法 | 打开 alert 弹框 | (message, title, options?) => Promise<MessageBoxData> | — |
PxMessageBox.confirm | ? 方法 | 打开 confirm 弹框 | (message, title, options?) => Promise<MessageBoxData> | — |
PxMessageBox.prompt | ? 方法 | 打开 prompt 弹框 | (message, title, options?) => Promise<MessageBoxData> | — |
PxMessageBox.close | ? 方法 | 关闭当前弹框 | () => void | — |
Alert 消息提示
用于提示用户的消息,只有确认按钮。
<template>
<px-button @click="showAlert">Show Alert</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showAlert = () => {
PxMessageBox.alert('This is an alert message', 'Alert').catch(() => {});
};
</script>Confirm 确认消息
用于提示用户确认操作,有确认和取消按钮。
<template>
<px-button @click="showConfirm">Show Confirm</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showConfirm = async () => {
try {
await PxMessageBox.confirm('Are you sure to delete this item?', 'Confirm');
PxMessage.success('Deleted successfully');
} catch {
PxMessage.info('Cancelled');
}
};
</script>Prompt 提交内容
用于提示用户输入内容。
<template>
<px-button @click="showPrompt">Show Prompt</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showPrompt = async () => {
try {
const { value } = await PxMessageBox.prompt('Please input your name', 'Prompt');
PxMessage.success(`Your name is: ${value}`);
} catch {
PxMessage.info('Cancelled');
}
};
</script>自定义内容
可以自定义消息框的内容。
<template>
<px-button @click="showCustom">Custom MessageBox</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showCustom = async () => {
try {
await PxMessageBox({
title: 'Warning',
message: 'This action will permanently delete the file. Continue?',
type: 'warning',
showCancelButton: true,
confirmButtonText: 'Yes, delete it',
cancelButtonText: 'No, cancel',
});
PxMessage.success('Deleted!');
} catch {
PxMessage.info('Cancelled');
}
};
</script>居中布局
使用 center 属性使标题和底部按钮居中对齐。
<template>
<px-button @click="showCenter">Center Layout</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showCenter = () => {
PxMessageBox({
title: 'Warning',
message: 'This will center the title and footer.',
type: 'warning',
center: true,
showCancelButton: true,
}).catch(() => {});
};
</script>关闭前回调
使用 beforeClose 拦截关闭操作。回调接收 action、instance 和 done 函数 — 调用 done() 才会真正关闭对话框。如果 beforeClose 返回一个 Promise,被点击的按钮会自动显示加载状态,直到 Promise 完成。
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="showCallbackStyle">Callback Style</px-button>
<px-button @click="showAsyncStyle">Async / Promise Style</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showCallbackStyle = () => {
PxMessageBox({
title: 'Confirm',
message: 'Are you sure? The dialog will close after 1 second.',
showCancelButton: true,
beforeClose: (action, _instance, done) => {
if (action === 'confirm') {
setTimeout(() => {
done();
PxMessage.success('Confirmed after delay');
}, 1000);
} else {
done();
}
},
});
};
const showAsyncStyle = () => {
PxMessageBox({
title: 'Async Confirm',
message: 'The confirm button will show a loading spinner for 1.5 seconds.',
showCancelButton: true,
beforeClose: (action, _instance, done) => {
if (action === 'confirm') {
return new Promise<void>((resolve) => {
setTimeout(() => {
done();
PxMessage.success('Async operation completed');
resolve();
}, 1500);
});
}
done();
},
});
};
</script>类型彩色边框
将 type 设置为 'info'、'success'、'warning' 或 'danger',边框、阴影和分割线会显示对应的主题颜色。
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button type="info" @click="showType('info')">Info</px-button>
<px-button type="success" @click="showType('success')">Success</px-button>
<px-button type="warning" @click="showType('warning')">Warning</px-button>
<px-button type="danger" @click="showType('danger')">Danger</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showType = (type: 'info' | 'success' | 'warning' | 'danger') => {
PxMessageBox({
title: `${type.charAt(0).toUpperCase() + type.slice(1)} Type`,
message: `This message box uses the "${type}" type, which colors the border, shadow, and divider.`,
type,
showCancelButton: true,
}).catch(() => {});
};
</script>自定义外观
使用 customClass、customStyle 和 width 自定义对话框外观。width 接受数字(像素)或 CSS 字符串值。
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="showCustomClass">Custom Class</px-button>
<px-button @click="showCustomStyle">Custom Style</px-button>
<px-button @click="showWidth">Custom Width</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showCustomClass = () => {
PxMessageBox.alert('This dialog has a custom CSS class applied.', 'Custom Class', {
customClass: 'my-custom-msgbox',
}).catch(() => {});
};
const showCustomStyle = () => {
PxMessageBox.alert('This dialog has custom inline styles.', 'Custom Style', {
customStyle: {
'--px-message-box-bg': '#f0f9eb',
'--px-message-box-border-color': '#67c23a',
} as any,
}).catch(() => {});
};
const showWidth = () => {
PxMessageBox.alert('This dialog is 600px wide.', 'Custom Width (number)', { width: 600 }).catch(
() => {},
);
};
</script>
<style>
.my-custom-msgbox {
--px-message-box-bg: #fdf6ec;
--px-message-box-border-color: #e6a23c;
}
</style>关闭控制
使用 closeOnPressEscape 和 closeOnHashChange 控制对话框的关闭方式,两者默认均为 true。
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="showNoEscape">Disable ESC Close</px-button>
<px-button @click="showNoHashChange">Disable Hash Close</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showNoEscape = () => {
PxMessageBox({
title: 'No ESC Close',
message: 'Pressing Escape will NOT close this dialog. Use the buttons instead.',
showCancelButton: true,
closeOnPressEscape: false,
}).catch(() => {});
};
const showNoHashChange = () => {
PxMessageBox({
title: 'No Hash Close',
message: 'Changing the URL hash will NOT close this dialog.',
showCancelButton: true,
closeOnHashChange: false,
}).catch(() => {});
};
</script>输入验证
使用 inputSchema 配合 Zod schema 在确认前验证 prompt 输入。设置 inputErrorMessage 可自定义验证失败时输入框下方显示的错误文本。
<template>
<px-button @click="showValidation">Email Validation</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
import { z } from 'zod';
const showValidation = async () => {
try {
const { value } = await PxMessageBox.prompt(
'Please enter your email address',
'Email Validation',
{
inputPlaceholder: 'user@example.com',
inputSchema: z.string().email(),
inputErrorMessage: 'Please enter a valid email address',
},
);
PxMessage.success(`Email submitted: ${value}`);
} catch {
PxMessage.info('Cancelled');
}
};
</script>区分取消与关闭
当 distinguishCancelAndClose 为 true(默认)时,点击关闭按钮会以 'close' 拒绝,而点击取消按钮会以 'cancel' 拒绝。设置为 false 时两者均触发 'cancel'。
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="show(true)">Distinguish (default)</px-button>
<px-button @click="show(false)">Not Distinguished</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const show = async (distinguish: boolean) => {
try {
await PxMessageBox({
title: distinguish ? 'Distinguish Close' : 'Not Distinguished',
message: distinguish
? 'Close button fires "close", cancel button fires "cancel".'
: 'Both close button and cancel button fire "cancel".',
showCancelButton: true,
distinguishCancelAndClose: distinguish,
});
PxMessage.success('Action: confirm');
} catch (action) {
PxMessage.info(`Action: ${action}`);
}
};
</script>可拖拽
将 draggable 设置为 true,用户可以通过拖拽标题栏移动对话框。对话框会被约束在视口范围内。
<template>
<px-button @click="showDraggable">Draggable MessageBox</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showDraggable = () => {
PxMessageBox({
title: 'Draggable',
message: 'Drag the header to move this dialog around.',
showCancelButton: true,
draggable: true,
}).catch(() => {});
};
</script>自定义底部
使用 footer 选项提供一个 VNode 或渲染函数,替换默认的取消/确认按钮为自定义内容。
<template>
<px-button @click="showCustomFooter">Custom Footer</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
import { h } from 'vue';
const showCustomFooter = () => {
PxMessageBox({
title: 'Custom Footer',
message: 'This dialog replaces the default buttons with a custom footer.',
footer: () =>
h('div', { style: 'text-align: center; padding: 8px 0' }, [
h(
'a',
{
href: '#',
style: 'color: var(--px-color-primary); cursor: pointer',
onClick: (e: Event) => {
e.preventDefault();
PxMessageBox.close();
},
},
'I have read and agree to the terms',
),
]),
}).catch(() => {});
};
</script>