在 Vue 的世界里,插件就像是一把万能钥匙,它能让我们将通用功能封装成可复用的模块,实现 全局能力扩展。今天我们将从零开发一个全局通知插件,让你的 Vue 应用拥有优雅的消息提示能力!
Vue3 官方中文文档传送点: 插件 | Vue.js
插件开发的核心是理解 install 方法 和 全局资源注册 的机制
Vue前端成仙之路:Vue 前端成仙之路_野生的程序媛的博客-CSDN博客
GO后端成神之路:Go 后端成神之路_野生的程序媛的博客-CSDN博客
场景 | 实现方式 | 典型案例 |
---|---|---|
全局组件注册 | app.component() | Element Plus 组件库 |
全局指令添加 | app.directive() | v-loading 指令 |
全局混入逻辑 | app.mixin() | 权限校验逻辑 |
全局属性/方法注入 | app.config.globalProperties | $axios 实例 |
// plugins/notification.js
export default {
install: (app, options) => {
// 在这里注册全局资源
}
}
import { h, render, ref } from 'vue'
// 1. 创建通知容器组件
const NotificationContainer = {
setup() {
const notifications = ref([])
// 添加通知
const add = (notification) => {
notifications.value.push(notification)
// 自动关闭
if (notification.duration > 0) {
setTimeout(() => {
remove(notification.id)
}, notification.duration)
}
}
// 移除通知
const remove = (id) => {
notifications.value = notifications.value.filter(n => n.id !== id)
}
return { notifications, add, remove }
},
render() {
return h('div', { class: 'notification-container' },
this.notifications.map(notification =>
h(NotificationItem, {
key: notification.id,
...notification,
onClose: () => this.remove(notification.id)
})
)
)
}
}
// 2. 单个通知项组件
const NotificationItem = {
props: ['type', 'message', 'onClose'],
render() {
return h('div', { class: ['notification', this.type] }, [
h('span', this.message),
h('button', { onClick: this.onClose }, '×')
])
}
}
// 3. 插件安装逻辑
export default {
install(app) {
// 创建挂载节点
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
// 渲染通知容器
render(h(NotificationContainer), mountNode)
// 注入全局方法
app.config.globalProperties.$notify = {
show: (message, options = {}) => {
const id = Date.now()
const notification = {
id,
message,
type: options.type || 'info',
duration: options.duration || 3000
}
// 通过事件总线触发添加
const event = new CustomEvent('add-notification', { detail: notification })
document.dispatchEvent(event)
}
}
// 监听添加事件
document.addEventListener('add-notification', (e) => {
const instance = mountNode._vnode.component.ctx
instance.add(e.detail)
})
}
}
.notification-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
}
.notification {
padding: 12px 20px;
margin-bottom: 10px;
border-radius: 4px;
background: #f4f4f5;
color: #909399;
min-width: 200px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 12px rgba(0,0,0,.1);
}
.notification.success {
background: #f0f9eb;
color: #67c23a;
}
.notification.error {
background: #fef0f0;
color: #f56c6c;
}
import { createApp } from 'vue'
import App from './App.vue'
import notification from './plugins/notification'
import './styles/notification.css'
const app = createApp(App)
app.use(notification)
app.mount('#app')
// types/notification.d.ts
import { ComponentPublicInstance } from 'vue'
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$notify: {
show: (message: string, options?: NotificationOptions) => void
}
}
}
interface NotificationOptions {
type?: 'info' | 'success' | 'error'
duration?: number
}
// 使用 Pinia 管理通知状态
import { defineStore } from 'pinia'
export const useNotificationStore = defineStore('notification', {
state: () => ({
list: []
}),
actions: {
add(notification) {
this.list.push(notification)
},
remove(id) {
this.list = this.list.filter(n => n.id !== id)
}
}
})
通过开发全局通知插件,我们掌握了 Vue 插件开发的 核心模式:利用 install 方法扩展全局能力。插件开发的关键点在于: