vue-vben-admin 中 Vben Alert 轻量提示框的完整使用指南:alert / confirm / prompt 命令式调用与源码解析
【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin
Vben Alert是 vue-vben-admin 中基于纯 JavaScript 命令式调用的一族轻量提示框能力,通过alert、confirm、prompt三个函数即可快速完成简单确认、提示与轻量输入交互,无需在页面中手动维护弹窗组件与开关状态。读完本文,你将掌握这三种弹窗的全部参数、Promise 结果约定、beforeClose拦截、useAlertContext上下文调用,以及它们与复杂场景下Vben Modal的取舍。
Alert 是什么:轻量弹窗的定位与适用场景
Alert是一组纯 JavaScript 调用的轻量提示框(官方文档),与Modal的能力有部分重叠,但定位明确:
- 适合临时确认、简单提示和轻量输入场景,例如删除确认、操作结果提示、单字段输入。
- 复杂弹窗(多字段表单、复杂布局、长流程交互)仍建议使用
Vben Modal,Modal提供的是声明式组件 + 状态控制的完整弹窗方案。
Alert以命令式函数(imperative)形式工作:调用alert()、confirm()、prompt()即可在document.body下动态创建弹窗实例,返回 Promise,用户点击按钮后 Promise 被 resolve/reject。它无需在业务组件模板中声明任何弹窗标签,也没有v-model开关状态,代码更精简。
HMR 注意:通过
alert、confirm、prompt动态创建的弹窗,在已经打开的情况下不支持 HMR 热更新。修改相关代码后,需要先关闭弹窗再重新打开才能看到新效果。
基础用法:alert、confirm、prompt
三个函数的导出入口位于 packages/@core/ui-kit/popup-ui/src/alert/index.ts,内部实现由AlertBuilder提供(vbenAlert、vbenConfirm、vbenPrompt),对外统一命名为alert、confirm、prompt,并从@vben/common-ui导出。
alert:只有确认按钮的提示框
alert创建只有一个确认按钮的提示框,点击确认后 Promise 被 resolve。基础示例见 demos/vben-alert/alert/index.vue:
import { alert } from '@vben/common-ui'; function showAlert() { alert('This is an alert message'); }带图标与自定义内容:
function showIconAlert() { alert({ content: 'This is an alert message with icon', icon: 'success', }); } function showCustomAlert() { alert({ buttonAlign: 'center', content: h(Result, { status: 'success', subTitle: '已成功创建订单。订单ID:2017182818828182881', title: '操作成功', }), }); }content既可以是字符串,也可以是 Vue 组件(如h(Result, ...)渲染函数产生的 VNode),这使得提示框可以承载富内容。
confirm:带确认和取消按钮
confirm在alert基础上默认开启取消按钮(showCancel: true),并约定Promise 结果语义:点击确认 resolve,点击取消或按 Esc 关闭时 reject(错误信息为dialog cancelled)。示例见 demos/vben-alert/confirm/index.vue:
import { alert, confirm } from '@vben/common-ui'; function showConfirm() { confirm('This is an alert message') .then(() => { alert('Confirmed'); }) .catch(() => { alert('Canceled'); }); }这段代码对应的 Promise 语义与 alert-builder.test.ts 中的测试完全一致:
- 点击确认按钮:
await expect(promise).resolves.toBeUndefined(); - 点击取消按钮:
await expect(promise).rejects.toThrow('dialog cancelled'); - 按下 Esc:同样
rejects.toThrow('dialog cancelled')。
自定义确认/取消文案与底部内容:
function showFooterConfirm() { const checked = ref(false); confirm({ cancelText: '不要虾扯蛋', confirmText: '是的,我们都是NPC', content: '刚才发生的事情,为什么我似乎早就经历过一般?', footer: () => h(Checkbox, { checked: checked.value, 'onUpdate:checked': (v) => (checked.value = v), }, '不再提示'), icon: 'question', title: '未解之谜', }).then(() => { if (checked.value) { message.success('我不会再拿这个问题烦你了'); } }); }footer与content一样可以是字符串或组件,渲染在与按钮相同的容器中。
prompt:可接收用户输入的提示框
prompt在确认/取消的基础上增加了一个输入组件,通过component指定任意输入组件(默认是Input),返回值即为用户输入的值。基础示例见 demos/vben-alert/prompt/index.vue:
import { alert, prompt } from '@vben/common-ui'; function showPrompt() { prompt({ content: '请输入一些东西' }) .then((val) => { alert(`已收到你的输入:${val}`); }) .catch(() => { alert('Canceled'); }); }接入任意组件并绑定值:
function showSelectPrompt() { prompt({ component: Select, componentProps: { options: [ { label: 'Option A', value: 'Option A' }, { label: 'Option B', value: 'Option B' }, { label: 'Option C', value: 'Option C' }, ], placeholder: '请选择', // 弹窗会设置 body 的 pointer-events 为 none,这会影响下拉框的点击事件,需要显式恢复 popupClassName: 'pointer-events-auto', }, content: '此弹窗演示了如何使用 component 传递自定义组件', icon: 'question', modelPropName: 'value', }).then((val) => { if (val) alert(`你选择了${val}`); }); }要点:
modelPropName指定输入组件双向绑定的属性名,默认是modelValue(对应Input),改为value可适配Select、RadioGroup等传统组件;- 弹窗打开时
body的pointer-events会被置为none,这会阻断下拉面板等浮层的点击,因此示例中通过popupClassName: 'pointer-events-auto'恢复点击; componentProps透传给输入组件,componentSlots可传递插槽(函数、对象、VNode 皆可)。
AlertProps 与 PromptProps 完整参数说明
AlertProps的定义见 packages/@core/ui-kit/popup-ui/src/alert/alert.ts,字段如下:
| 参数 | 类型 | 说明 |
|---|---|---|
beforeClose | (scope: { isConfirm: boolean }) => boolean \| Promise<boolean \| undefined> \| undefined | 关闭前的回调,返回false则终止关闭(可用于异步校验) |
bordered | boolean | 是否显示边框,默认true(源码中withDefaults定义) |
buttonAlign | 'center' \| 'end' \| 'start' | 按钮对齐方式,默认'end'(右对齐) |
cancelText | string | 取消按钮文案,默认取$t('cancel')国际化值 |
centered | boolean | 是否居中显示,默认true |
confirmText | string | 确认按钮文案,默认取$t('confirm')国际化值 |
containerClass | string | 弹窗容器的额外 class |
content | Component \| string | 弹窗内容(必填语义),字符串自动渲染换行 |
contentClass | string | 内容区域的额外 class |
contentMasking | boolean | 执行beforeClose期间,在内容区域显示 loading 遮罩 |
escapeKeyClose | boolean | 按下 Esc 是否关闭弹窗,默认true;与全局配置globalEscapeShortcutKey任一为true即生效 |
footer | Component \| string | 底部内容(与按钮同容器) |
icon | Component \| IconType | 标题前的图标,IconType = 'error' \| 'info' \| 'question' \| 'success' \| 'warning' |
overlayBlur | number | 遮罩模糊效果 |
showCancel | boolean | 是否显示取消按钮,alert默认关闭、confirm默认开启 |
title | string | 弹窗标题,未传时alert默认取$t('prompt') |
PromptProps<T>在Omit<AlertProps, 'beforeClose'>基础上扩展:
| 参数 | 类型 | 说明 |
|---|---|---|
component | Component | 接受用户输入的组件,默认Input |
componentProps | Recordable<any> | 输入组件的属性 |
componentSlots | (() => any) \| Recordable<unknown> \| VNode \| VNodeArrayChildren | 输入组件的插槽 |
defaultValue | T | 输入框默认值 |
modelPropName | string | 值绑定属性名,默认modelValue |
图标类型的映射关系同样可以在 alert.vue 中查到:error对应红色CircleX、info对应Info、question对应CircleHelp、success对应绿色CircleCheckBig、warning对应CircleAlert,颜色使用主题 CSS 变量(--destructive、--info、--success、--warning),因此能随主题自动适配。
三种调用签名的重载规则
alert与confirm都支持三种重载形式(PromptProps只支持对象形式):
// 形式一:仅传配置对象 alert({ content: 'msg', icon: 'success' }); // 形式二:字符串消息 + 可选配置 alert('msg', { buttonAlign: 'center' }); // 形式三:字符串消息 + 标题 + 可选配置 alert('msg', '标题', { icon: 'question' });AlertBuilder.ts中的实现逻辑为:若第一个参数是字符串则作为content;第二个参数是字符串则作为title、是对象则合并进配置;第三个对象参数继续合并。confirm的底层实现只是向alert注入showCancel: true默认值后透传,这一实现细节清晰体现了confirm与alert的关系。
beforeClose:关闭前的异步拦截
beforeClose在弹窗即将关闭时执行,接收{ isConfirm: boolean }作用域对象,返回false可阻止关闭,支持异步(返回 Promise)。
alert/confirm场景:
confirm({ beforeClose({ isConfirm }) { if (isConfirm) { // 这里可以执行一些异步操作,如果最终返回了 false,将阻止关闭弹窗 return new Promise((resolve) => setTimeout(resolve, 2000)); } }, content: 'This is an alert message with async confirm', icon: 'success', }).then(() => { alert('Confirmed'); });prompt场景下作用域对象额外包含value(当前输入值),可以结合输入内容做校验:
function showAsyncPrompt() { prompt({ async beforeClose(scope) { if (scope.isConfirm) { if (scope.value) { await sleep(2000); // 模拟异步操作,如果不成功,可以返回 false } else { alert('请选择一个选项'); return false; } } }, component: RadioGroup, componentProps: { options: [ { label: 'Option 1', value: 'option1' }, { label: 'Option 2', value: 'option2' }, { label: 'Option 3', value: 'option3' }, ], }, content: '选择一个选项后再点击[确认]', icon: 'question', modelPropName: 'value', }).then((val) => { alert(`${val} 已设置。`); }); }底层实现(AlertBuilder.ts)会在prompt中包装用户传入的beforeClose:将其与modelValue合并为{ isConfirm, value }后再调用,随后经alert.vue的handleOpenChange执行:
async function handleOpenChange(val: boolean) { await nextTick(); // 等待标记 isConfirm 状态 if (!val && props.beforeClose) { loading.value = true; try { const res = await props.beforeClose({ isConfirm: isConfirm.value }); if (res !== false) { open.value = false; } } finally { loading.value = false; } } else { open.value = val; } }结合contentMasking: true(prompt默认开启),beforeClose执行期间内容区域会显示 loading 遮罩,避免用户重复操作。测试 alert.test.ts 覆盖了该组件的关闭行为。
useAlertContext:在自定义组件内触发确认/取消
当content、footer或icon使用自定义组件时,可以在这些组件内部通过useAlertContext()获取当前弹窗上下文,主动触发确认或取消。
限制:
useAlertContext只能在setup或函数式组件中使用。
Methods
| 方法 | 描述 | 类型 | 版本要求 |
|---|---|---|---|
doConfirm | 触发当前弹窗的确认操作 | () => void | >5.5.4 |
doCancel | 触发当前弹窗的取消操作 | () => void | >5.5.4 |
实现上(alert.ts),上下文通过createContext创建(provideAlertContext/injectAlertContext),由alert.vue在渲染时provideAlertContext({ doCancel, doConfirm })注入,useAlertContext在未找到 Provider 时会抛出useAlertContext must be used within an AlertProvider错误,因此必须在弹窗内容组件内使用。
典型用法:自定义输入组件中按下回车直接确认。
import { useAlertContext } from '@vben/common-ui'; function showSlotsPrompt() { prompt({ component: () => { // 获取弹窗上下文。注意:只能在 setup 或者函数式组件中调用 const { doConfirm } = useAlertContext(); return h(Input, { onKeydown(e: KeyboardEvent) { if (e.key === 'Enter') { e.preventDefault(); // 调用弹窗提供的确认方法 doConfirm(); } }, placeholder: '请输入', prefix: '充值金额:', type: 'number', }, { addonAfter: () => h(BadgeJapaneseYen), }); }, content: '此弹窗演示了如何使用自定义插槽,并且可以使用 useAlertContext 获取到弹窗的上下文。\n在输入框中按下回车键会触发确认操作。', icon: 'question', modelPropName: 'value', }).then((val) => { if (val) alert(`你输入的是${val}`); }); }命令式弹窗的底层原理:动态挂载与 Promise 生命周期
从源码结构看,alert命令式能力由三层协作完成(AlertBuilder.ts + alert.vue):
- 动态挂载:调用时
document.createElement('div')创建容器并document.body.append(container),用 Vue 的h()创建Alert组件 VNode 后render(vnode, container)渲染,实现"零模板声明"。 - Promise 生命周期:
onClosed(isConfirm)回调中先render(null, container)卸载组件、移除容器 DOM,再根据isConfirm决定resolve()还是reject(new Error('dialog cancelled'))——这正是上文 Promise 语义的来源。 - Esc 与取消处理:Esc 按下时
isConfirm被标记为false,因此走 reject 分支;若组件参数escapeKeyClose与全局配置globalEscapeShortcutKey均为false才阻止关闭(见 alert.vue)。
同时AlertBuilder维护了alerts数组记录所有活动实例,并提供clearAllAlerts()一键卸载全部弹窗;alert-builder.test.ts 中的测试验证了clearAllAlerts会移除所有挂载容器。prompt的输入组件在onOpened时自动聚焦(优先组件 exposed 的focus,否则按input/select/textarea/button选择可聚焦元素),提升键盘操作体验。
结语
Vben Alert以三个命令式函数覆盖了"提示—确认—轻量输入"的完整交互光谱:字符串/组件双形态的content、五类内置图标、beforeClose异步拦截、useAlertContext上下文联动,以及自动聚焦、Esc 关闭、loading 遮罩等细节打磨。在 vue-vben-admin 中,遇到临时确认、简单提示和单字段输入时优先使用Alert三函数,能显著减少样板代码;需要多字段表单或复杂布局时再切换到Vben Modal。更多 API 细节可查阅 官方文档 与 popup-ui 源码。
【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考