玩转Notification通知实现与优化的那些事儿
项目背景和选型
最近做了一个电商后台管理系统,需求里要求有个全局的通知功能。说白了就是用户操作后给个反馈,比如“删除成功”“添加成功”这种提示。
本来想用Element Plus自带的Notification组件,但发现样式定制性太差,而且在多标签页场景下会有问题。最后决定自己封装一个轻量的通知组件,基于Vue 3和TypeScript实现。
踩坑:样式冲突和动画问题
开始写的时候挺顺利,用了个简单的绝对定位把通知框放在右上角。结果一上线就发现问题了:
- 多个通知同时出现时会重叠
- 动画效果生硬,关闭时直接消失了
- 在不同分辨率下位置会偏移
折腾了半天才发现是CSS优先级和transform的问题。下面是调整后的核心代码:
// notification.ts
import { createApp, ref } from 'vue'
import NotificationComponent from './Notification.vue'
const notifications = ref([])
export function useNotification() {
const add = (message: string, type: 'success' | 'error' = 'success') => {
const id = Date.now()
notifications.value.push({ id, message, type })
// 自动移除
setTimeout(() => {
remove(id)
}, 3000)
}
const remove = (id: number) => {
const index = notifications.value.findIndex(n => n.id === id)
if (index > -1) notifications.value.splice(index, 1)
}
return { notifications, add, remove }
}
export function createNotification() {
const mountPoint = document.createElement('div')
document.body.appendChild(mountPoint)
const app = createApp(NotificationComponent, {
notifications: useNotification().notifications
})
app.mount(mountPoint)
}
最大的挑战:多实例管理
当系统同时触发多个通知时,事情变得复杂了。最开始我简单地用一个数组存通知,结果发现:
- 快速连续触发会导致通知闪烁
- 关闭动画还没完成就被移除了
- 有些通知会被错误地覆盖
后来改用队列的方式来处理,每个通知都有独立的生命周期控制。这是优化后的样式部分:
/* notification.css */
.notification-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 10px;
}
.notification-item {
background: #fff;
border: 1px solid #ddd;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 10px 20px;
border-radius: 4px;
opacity: 0;
transform: translateX(100%);
transition: all 0.3s ease;
}
.notification-item.show {
opacity: 1;
transform: translateX(0);
}
.notification-item.hide {
opacity: 0;
transform: translateX(100%);
}
意外收获:API封装
写着写着发现,与其让用户手动调用add方法,不如封装成更简单的API。于是加了个工厂函数:
// api.ts
import { createNotification, useNotification } from './notification'
let instance: any = null
export function notify(message: string, type: 'success' | 'error' = 'success') {
if (!instance) {
instance = createNotification()
}
useNotification().add(message, type)
}
// 使用方式
notify('操作成功', 'success')
notify('出错了', 'error')
这个改动虽然小,但大大提升了使用体验。现在其他开发者只需要引入一个简单的notify函数就能用了。
遗留问题和性能考虑
虽然基本功能都实现了,但还是有几个小问题没完全解决:
- 在某些老旧浏览器上动画性能不够流畅
- 当通知数量超过5个时,堆积效果不太理想
- 没有做国际化支持
性能方面,目前每次新增或移除通知都会触发视图更新。考虑过用虚拟DOM优化,但觉得现阶段影响不大就没继续深挖了。
回顾与反思
总的来说,这个通知组件比我预想的要复杂。从最初以为几个小时能搞定,到最后花了三天才勉强满意。但也正因为这些坑,让我对Vue的响应式原理理解更深了。
如果让我重新来一遍,我可能会:
- 提前规划好动画方案
- 一开始就考虑多实例的情况
- 做好单元测试覆盖
以上是我个人对这个Notification组件的完整讲解,有更优的实现方式欢迎评论区交流。这个组件后续还会继续迭代,等有了新进展再跟大家分享。
本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。

暂无评论