Vue Ionic 如何实现全局接收推送并同步更新通知组件列表?
实现方案
完全可以满足需求,核心思路是将通知的存储从通知组件的局部状态,抽离为全局可访问的状态,这样全局推送监听器收到的通知可以统一存储,不管应用当前停在哪个业务页面,等用户后续打开通知组件时,直接从全局存储读取所有已接收的通知即可。
具体实现步骤
第一步:在全局状态管理中定义通知存储模块
利用项目已经引入的Vuex,新建独立的通知状态模块,用来持久化(应用运行期间)存储所有收到的实时推送通知,提供修改通知列表的方法:// store/modules/notification.js export default { namespaced: true, state: () => ({ // 存储应用运行期间收到的所有实时推送通知 realtimeNotificationList: [] }), mutations: { // 新增单条实时通知到列表头部 addNewNotification(state, notification) { state.realtimeNotificationList.unshift(notification) }, // 可选方法:清空通知列表 clearAllNotifications(state) { state.realtimeNotificationList = [] } } }第二步:修改main.js中的全局推送监听逻辑
收到推送通知时,直接将通知写入全局状态存储,无需考虑当前应用打开的是哪个页面——因为全局状态在应用运行期间是常驻存在的,不会因为路由切换、组件销毁而丢失:// main.js import { createApp } from 'vue' import App from './App.vue' import store from './store' // 引入全局store实例 import { PushNotifications } from '@capacitor/push-notifications' const app = createApp(App) app.use(store) // 注册全局推送接收监听 PushNotifications.addListener('pushNotificationReceived', (notification) => { // 收到通知直接提交到全局store存储 store.commit('notification/addNewNotification', notification) // 可根据业务需求补充其他逻辑,比如更新应用图标角标 } ) app.mount('#app')第三步:修改通知组件的读取逻辑
把原来组件内部维护的本地通知列表,替换为从全局状态读取的数据,同时合并接口返回的历史未读通知,保证页面打开时能同时展示历史通知和应用在其他页面时收到的所有实时通知。同时修正原代码中通知列表类型定义错误的问题:<script> import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonIcon, IonButtons, IonButton, IonList, IonItem, IonLabel, } from "@ionic/vue"; import { logOut } from "ionicons/icons"; import { mapState } from "vuex"; import { useRouter } from "vue-router"; import SideMenu from "./SideMenu.vue"; import { TokenService } from "@/services/token.service"; export default { name: "Tab1", components: { IonHeader, IonToolbar, IonTitle, IonContent, IonPage, IonIcon, IonButtons, IonButton, IonList, IonItem, IonLabel, }, data() { return { msg: "", }; }, computed: { // 从全局store映射实时通知列表 ...mapState('notification', { realtimeNotifications: state => state.notification.realtimeNotificationList }), // 合并历史通知+实时收到的通知,作为页面最终展示的列表 notifications() { const historyNotifications = TokenService.getUserInfo().unread_notifications || [] // 合并时可根据通知id去重,避免重复渲染 const notificationMap = new Map() [...this.realtimeNotifications, ...historyNotifications].forEach(item => { notificationMap.set(item.id || item.data?.id, item) }) return Array.from(notificationMap.values()) } }, // 原有mounted中的本地通知赋值逻辑可移除 mounted() { // 可根据需求补充:每次进入通知页时刷新历史未读通知数据 } }; </script>
补充说明
- 该方案不依赖通知组件的挂载状态:哪怕用户收到推送时,通知组件从未被打开过(实例根本不存在),通知也会正常存入全局状态,等用户后续进入通知页面时可以完整展示。
- 如果需要应用重启后依然能看到之前收到的通知,可以在全局存储通知时,同步将列表写入本地持久化存储(如Ionic Storage),应用启动时再从本地读取之前存储的通知恢复到全局状态即可。
- 原组件模板中的列表渲染逻辑(
v-if="this.notifications.length > 0"、循环渲染通知项)不需要做额外修改,适配数组类型的通知列表后即可正常运行。
内容的提问来源于stack exchange,提问作者Bilal Arshad
相关产品推荐
相关产品推荐

