☰
Element Plus Notification 通知组件完全指南:全局调用、类型体系与源码级原理剖析
2026/10/4 10:46:22 网站建设 项目流程

Element Plus Notification 通知组件完全指南:全局调用、类型体系与源码级原理剖析

【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus

Notification 是 Element Plus 提供的一款全局消息通知组件,用于在页面四角弹出轻量级的提示卡片,适合承载操作结果、系统消息等非阻塞性反馈。本文以 notification.md 官方文档为主线,结合 notification 组件源码 与官方示例,系统讲解其调用方式、全部配置项、版本演进能力(如 VNode 消息、倒计时进度条、hover 暂停等),并深入到实例队列管理、定时器与 zIndex 分配的底层实现,帮助你从"会调用"进阶到"知其所以然"。

基础用法:第一个 Notification

Element Plus 已将$notify方法注册到app.config.globalProperties,因此在任意 Vue 组件内部可以直接通过this.$notify调用;在<script setup>组合式 API 中,更推荐按需导入ElNotification后直接调用函数式 API。

最简单的场景只需提供title(标题)和message(正文)两个字段:

import { ElNotification } from 'element-plus' ElNotification({ title: 'Title', message: 'This is a reminder', })

参考官方示例 notification/basic.vue,其默认行为是在 4500ms 后自动关闭,你可以在创建时传入h('i', ...)渲染的 VNode 作为消息体:

import { h } from 'vue' import { ElNotification } from 'element-plus' const open1 = () => { ElNotification({ title: 'Title', message: h('i', { style: 'color: teal' }, 'This is a reminder'), }) }

若希望通知永不自动关闭,将duration设置为0即可:

const open2 = () => { ElNotification({ title: 'Prompt', message: 'This is a message that does not automatically close', duration: 0, }) }

注意:duration接收的是毫秒单位的 Number。

在源码层面,notification.ts 中duration的默认值即为4500,而 notification.vue 的startTimer()会先判断props.duration <= 0并直接返回——这正是duration: 0不自动关闭的实现依据。

五种通知类型:primary / success / warning / info / error

Notification 通过type字段指定语义类型,组件会据此渲染对应的图标与状态色。官方文档明确列出四种基础类型,而primary类型在 ^(2.9.11) 版本中新增,因此当前共有五种:

type语义说明
primary主色^(2.9.11) 新增,无状态色
success成功绿色、对勾图标
warning警告橙色、感叹号图标
info信息蓝色、信息图标
error错误红色、叉号图标

除了在ElNotification({ type: 'success' })中显式传参,Element Plus 还为每种类型注册了独立方法,可以直接调用而无需传入type:

ElNotification.success({ title: 'Success', message: 'This is a success message' }) ElNotification.warning({ title: 'Warning', message: 'This is a warning message' }) ElNotification.info({ title: 'Info', message: 'This is an info message' }) ElNotification.error({ title: 'Error', message: 'This is an error message' }) ElNotification.primary({ title: 'Primary', message: 'This is a primary message' })

完整示例见 notification/different-types.vue。

源码佐证:在 notification.ts 中,类型数组被定义为['primary', 'success', 'info', 'warning', 'error'];而 notify.ts 遍历该数组,为notify函数动态挂载了notify[type]方法,内部实现等价于notify({ ...options, type })。同时,notification.vue 中的iconComponent计算属性遵循"有type用类型图标,否则回退到自定义icon"的优先级规则,印证了文档中"icon会被type覆盖"的说明。

自定义弹出位置:四个角落任选

Notification 可以从页面四个角落中的任意一个滑入,通过position字段控制,可选值为top-right、top-left、bottom-right、bottom-left,默认值为top-right。

ElNotification({ title: 'Custom Position', message: "I'm at the bottom right corner", position: 'bottom-right', })

参考官方示例 notification/positioning.vue,其中依次演示了右上(默认)、右下、左下、左上四种定位。

从源码看,位置不仅决定视觉坐标,还决定了实例队列的归属。notify.ts 内部维护了一个以四个位置为键的队列对象:

const notifications: Record<NotificationPosition, NotificationQueue> = { 'top-left': [], 'top-right': [], 'bottom-left': [], 'bottom-right': [], }

同位置的多个实例会按顺序纵向堆叠,彼此之间保持固定的 16px 间距(GAP_SIZE,见 notify.ts)。

调整屏幕边缘偏移:offset

通过offset属性可以控制 Notification 距屏幕边缘的偏移量。文档特别强调:同一时刻的每一个 Notification 实例应使用相同的 offset,否则会出现视觉错乱。

ElNotification.success({ title: 'Success', message: 'This is a success message', offset: 100, })

示例见 notification/offsetting.vue。

这里有必要解释offset的真实语义:notify.ts 在创建实例时,并非直接使用用户传入的offset,而是把它作为基础偏移,再叠加同位置队列中所有已存在实例的高度与间距,从而得到每个实例实际的纵向位置:

let verticalOffset = options.offset || 0 notifications[position].forEach(({ vm }) => { verticalOffset += (vm.el?.offsetHeight || 0) + GAP_SIZE }) verticalOffset += GAP_SIZE

因此offset更像"第一个实例距屏幕边缘的距离",后续实例会自动向下(或向上)排开,无需手动计算。

使用 HTML 字符串与 XSS 安全警告

message默认按纯文本渲染,若需渲染富文本,可将dangerouslyUseHTMLString设为true:

ElNotification({ title: 'HTML String', dangerouslyUseHTMLString: true, message: '<strong>This is <i>HTML</i> string</strong>', })

示例见 notification/raw-html.vue。

必须重视的安全警告:动态渲染任意 HTML 极易导致 XSS(跨站脚本)攻击。因此开启dangerouslyUseHTMLString后,请务必确保message内容可信,绝不要将用户输入直接作为message赋值。

该行为的实现位于 notification.vue:组件通过v-if="!dangerouslyUseHTMLString"走插值渲染,否则走v-html="message",源码注释中也明确标注了"never use user's input as message"。

消息即函数:VNode 与动态渲染 ^(2.9.0)

从 ^(2.9.0) 版本起,message除了支持字符串和 VNode 之外,还支持返回 VNode 的函数。函数形式的最大价值在于:当 VNode 中包含响应式动态属性时,只有函数形式才能保证内容跟随状态更新。

普通 VNode 写法:

import { h } from 'vue' ElNotification({ title: 'Use Vnode', message: h('p', null, [ h('span', null, 'Message can be '), h('i', { style: 'color: teal' }, 'VNode'), ]), })

包含动态 props(如开关组件)时必须使用函数形式:

import { h, ref } from 'vue' import { ElNotification, ElSwitch } from 'element-plus' const open1 = () => { const checked = ref<boolean | string | number>(false) ElNotification({ title: 'Use Vnode', // Should pass a function if VNode contains dynamic props message: () => h(ElSwitch, { modelValue: checked.value, 'onUpdate:modelValue': (val: boolean | string | number) => { checked.value = val }, }), }) }

完整示例见 notification/use-vnode.vue。其底层逻辑在 notify.ts:createVNode时会判断message是函数则直接作为插槽函数、是 VNode 则包一层箭头函数,从而把任意形式的message统一为可渲染的插槽内容。这也解释了为什么函数形式能保留动态响应能力——它本质上是作为作用域插槽被渲染的。

倒计时进度条与悬停暂停 ^(2.14.4)

从 ^(2.14.4) 起,Notification 支持显示一条与自动关闭计时同步的进度条,直观展示剩余展示时间。

  • 传入progress: true显示默认进度条,其颜色跟随type的状态色;
  • 传入对象可深度定制进度条,支持 Progress 组件 的全部选项(如color),但percentage、type、duration、indeterminate、width五个字段被排除——因为该进度条永远由倒计时驱动,percentage会自动计算;
  • 当pauseOnHover为true(默认值)时,鼠标悬停在通知上会同时暂停计时器与进度条。
ElNotification({ title: 'Default progress', message: 'Hover to pause the timer and progress bar', duration: 6000, progress: true, }) ElNotification({ title: 'Custom color', message: 'Custom progress bar color overrides the default', duration: 6000, progress: { color: [ { color: '#f56c6c', percentage: 20 }, { color: '#e6a23c', percentage: 40 }, { color: '#5cb87a', percentage: 60 }, { color: '#1989fa', percentage: 80 }, { color: '#6f7ad3', percentage: 100 }, ], }, }) // 悬停不暂停 ElNotification({ title: 'No pause on hover', message: 'Timer and progress bar keep running even when hovering', duration: 6000, progress: true, pauseOnHover: false, })

示例见 notification/progress-bar.vue。

源码层面的实现非常精巧,值得展开:

  • notification.ts 中NotificationProgress类型通过Omit<Partial<ProgressProps>, 'percentage' | 'type' | 'duration' | 'indeterminate' | 'width'>显式排除上述字段,与文档说明完全一致;
  • notification.vue 使用useIntervalFn以 100ms 为间隔更新percentage,计算公式为100 - ((elapsed + Date.now() - startedAt) / duration) * 100,即从 100 线性递减到 0;
  • 悬停暂停通过onMouseEnter/onMouseLeave配合clearTimer()/startTimer()实现(见 notification.vue),且clearTimer()会累计已流逝时间elapsed,恢复时用remaining = duration - elapsed重新计时并让进度条从当前位置继续,而不是粗暴归零;
  • 键盘交互同样周到:按下Esc关闭当前通知,按下Delete/Backspace则仅暂停计时(见 notification.vue)。

隐藏关闭按钮:showClose

默认情况下 Notification 右上角有关闭按钮,将其设为false后用户将无法手动关闭(只能等待自动关闭或通过代码调用close):

ElNotification({ title: 'Title', message: 'This is a message', showClose: false, })

对应示例见 notification/no-close.vue。组件模板中关闭按钮通过v-if="showClose"条件渲染(notification.vue),并使用了.stop修饰符阻止点击事件冒泡到通知卡片本身。

全局方法与局部引入

全局方法 $notify

Element Plus 将$notify注册到了app.config.globalProperties,因此任何 Vue 实例内部都可以直接调用:

this.$notify({ title: 'Title', message: 'This is a message', })

局部引入

在按需引入的场景下,推荐从element-plus显式导入ElNotification:

import { ElNotification } from 'element-plus' import { CloseBold } from '@element-plus/icons-vue' ElNotification({ title: 'Title', message: 'This is a message', closeIcon: CloseBold, })

同样支持类型化方法ElNotification.success(options)(以及primary、warning、info、error)。此外还提供两个批量控制方法:

  • ElNotification.closeAll():手动关闭当前所有通知实例。源码实现见 notify.ts,它遍历四个方向的队列并逐一调用实例暴露的close();
  • ElNotification.updateOffsets(position)(^(2.10.5) 新增):手动更新指定方向下所有实例的偏移量。源码见 notify.ts,它会以队列中首个实例的偏移为基准,重新按"高度 + 16px 间距"依次排布后续实例。

App 上下文继承

Notification 的构造函数接受第二个参数context,用于注入当前应用的上下文(app context),从而使通知内的组件可以继承当前应用的全部属性(如全局组件、provide/inject 数据等)。

import { getCurrentInstance } from 'vue' import { ElNotification } from 'element-plus' // in your setup method const { appContext } = getCurrentInstance()! ElNotification({}, appContext)

两点补充说明:

  • 若你通过app.use(ElementPlus)全局注册了ElNotification,它会自动继承应用上下文,无需手动传参;
  • 源码中 notify.ts 通过vm.appContext = isUndefined(context) ? notify._context : context完成注入,而notify._context正是全局注册时被赋值的应用上下文(notify.ts)。

API 参考:Options 完整配置表

下表为ElNotification(options)支持的全部配置项,字段、类型与默认值均与官方文档一致,并结合源码补充了版本与取值说明。

名称说明类型默认值
title标题string''
message正文内容string/VNode/() => VNode(函数形式 ^(2.9.0))''
dangerouslyUseHTMLString是否将message作为 HTML 字符串渲染(开启需防范 XSS)booleanfalse
type通知类型:'primary'(^(2.9.11))|'success'|'warning'|'info'|'error'|''enum''
icon自定义图标组件(会被type覆盖)string/Component—
customClass自定义类名string''
duration自动关闭前的时长(毫秒);设为0则不自动关闭number4500
position弹出位置:'top-right'|'top-left'|'bottom-right'|'bottom-left'enumtop-right
showClose是否显示关闭按钮booleantrue
onClose关闭时的回调() => void—
onClick点击通知时的回调() => void—
offset距屏幕边缘的偏移(同刻所有实例应保持一致)number0
appendTo通知挂载的根元素,默认document.bodyCSSSelector/HTMLElement—
zIndex初始 zIndexnumber0
closeIcon ^(2.9.8)自定义关闭图标string/ComponentClose
progress ^(2.14.4)自动关闭倒计时进度条:true显示默认条;传对象可定制(percentage、type、duration、indeterminate、width被排除)boolean/object(Progress 选项)false
pauseOnHover ^(2.14.4)悬停时是否暂停计时booleantrue

源码佐证:notification.ts 中的notificationProps完整定义了上述字段,其中position与type通过values做了枚举约束,closeIcon默认值为Close图标(源自@element-plus/icons-vue),progress使用definePropType([Boolean, Object])同时接受布尔与对象两种形态。

API 参考:实例方法

ElNotification(...)与this.$notify(...)都会返回当前 Notification 的实例句柄,可在任意时刻手动关闭:

名称说明类型
close关闭该条 Notification() => void
const notification = ElNotification({ title: 'Title', message: '...' }) // 手动关闭 notification.close()

该方法的内部实现值得留意:返回句柄的close并非直接隐藏 DOM,而是调用组件实例exposed中暴露的close()(见 notify.ts)。组件内部的close()会先置visible = false触发离场过渡,再执行clearTimer()停止进度条与关闭计时器(notification.vue),确保完整的生命周期不会被跳过。

深入原理:实例队列、内存清理与 zIndex

实例队列与自动排布

如前所述,notify.ts 用四个方向的数组维护所有存活实例。关闭某条通知时,close()(notify.ts)会做三件事:

  1. 调用用户传入的onClose回调;
  2. 在transition的before-leave阶段读取被移除实例的offsetHeight(此时 DOM 尚未卸载,可正常取高);
  3. 将该实例从队列中splice移除,并把其后方所有实例的偏移统一减去"被移除高度 + 16px 间距",实现后续通知平滑上移补位。

内存释放

每个通知创建时会生成一个独立的div容器,并通过render(vm, container)渲染(notify.ts)。组件在离场动画结束后触发destroy事件,对应onDestroy钩子执行render(null, container)卸载虚拟节点,防止内存泄漏。

层级管理

通知的zIndex默认并非固定的0:组件通过useGlobalComponentSettings获取全局 zIndex 管理器,在onMounted时调用nextZIndex()自增获取当前最高层级(notification.vue),确保新通知始终覆盖在旧通知之上;若显式传入zIndex则优先生效。

小结

Element Plus Notification 以"函数式调用 + 可配置化选项"为核心设计,从基础的标题/正文、四种语义类型,到定位偏移、VNode 消息、倒计时进度条、悬停暂停等进阶能力一应俱全。配合源码中精心设计的实例队列、过渡生命周期、zIndex 分配与内存清理机制,它在易用性与工程稳健性之间取得了很好的平衡。掌握本文所述的选项语义与底层行为,你便能在项目中正确、安全、优雅地使用通知能力。

如需继续了解与 Notification 同族的轻提示组件,可查阅 Message 组件文档 与 MessageBox 组件文档 进行对比选型。

【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询