UniApp 全局通知功能实现:从 Vue 3 兼容性问题到完整解决方案
本文记录了一个 UniApp 项目中全局通知功能的完整实现过程,重点解决了 Vue 3 API 在旧版本 HBuilderX 中的兼容性问题,并提供了完整的代码示例和实现思路。
问题背景
在开发 UniApp 应用时,我尝试实现一个全局通知功能,但在运行时遇到了白屏问题。经过排查,发现这是因为项目使用了 Vue 3 的 API,而当前使用的 HBuilderX 版本对 Vue 3 支持不完善导致的兼容性问题。
解决方案
1. 降级到 Vue 2 写法
首先需要将项目从 Vue 3 的写法改为 Vue 2 的兼容性写法。
main.js - 修复版
javascript
// 使用Vue 2的写法
import App from './App.vue'
import Vue from 'vue'
import './common/uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
2. 应用入口文件调整
App.vue - 修复版
vue
<script>
export default {
onLaunch() {
console.log('App启动')
// 设置一个简单的token模拟登录
uni.setStorageSync('token', 'test_token')
},
onShow() {
console.log('App Show')
},
onHide() {
console.log('App Hide')
}
}
</script>
<style>
/* 全局样式 */
page {
background-color: #f8f8f8;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, sans-serif;
}
.container {
padding: 20rpx;
}
</style>
核心功能实现
通知功能页面
创建一个功能完善的测试页面,包含多种通知类型和操作日志功能。
pages/index/index.vue - 核心代码结构
vue
<template>
<view class="container">
<!-- 页面头部 -->
<view class="header">
<text class="title">推送通知测试</text>
<text class="subtitle">点击按钮测试通知功能</text>
</view>
<!-- 功能按钮组 -->
<view class="button-group">
<button class="btn btn-primary" @tap="sendSimpleNotification">
发送简单通知
</button>
<button class="btn btn-success" @tap="sendDelayedNotification">
发送5秒延迟通知
</button>
<button class="btn btn-warning" @tap="sendCustomNotification">
发送自定义通知
</button>
<button class="btn btn-error" @tap="clearNotifications">
清空所有通知
</button>
</view>
<!-- 操作日志显示 -->
<view class="log-card">
<text class="log-title">操作日志:</text>
<scroll-view class="log-content" scroll-y>
<text class="log-item" v-for="(log, index) in logs" :key="index">{{ log }}</text>
</scroll-view>
</view>
</view>
</template>
通知功能方法实现
javascript
<script>
export default {
data() {
return {
messageCount: 1,
logs: []
}
},
methods: {
// 初始化推送功能
initPush() {
if (typeof plus === 'undefined') {
this.addLog('错误: plus对象未定义,请在真机上运行')
return
}
// 监听通知点击事件
plus.push.addEventListener('click', (msg) => {
this.addLog('通知被点击: ' + msg.content)
uni.showToast({
title: '点击了通知',
icon: 'success'
})
})
},
// 发送简单通知
sendSimpleNotification() {
const content = `这是第${this.messageCount}条测试消息`
plus.push.createMessage(
content,
JSON.stringify({ type: 'test', id: this.messageCount }),
{
title: '测试通知',
cover: false,
sound: 'system'
}
)
this.addLog('发送通知: ' + content)
this.messageCount++
},
// 发送延迟通知
sendDelayedNotification() {
plus.push.createMessage(
'这是5秒后显示的延迟通知',
JSON.stringify({ type: 'delayed', time: new Date() }),
{
title: '延迟通知',
delay: 5, // 5秒延迟
cover: false
}
)
},
// 清空所有通知
clearNotifications() {
plus.push.clear()
this.messageCount = 1
this.addLog('清空所有通知')
}
}
}
</script>
兼容性处理
Promise 兼容性适配
创建 common/uni.promisify.adaptor.js 文件处理 Promise 兼容性问题:
javascript
// common/uni.promisify.adaptor.js
if (!Promise.prototype.finally) {
Promise.prototype.finally = function(callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
}
配置文件
manifest.json - 配置 Android 通知权限:
json
{
"app-plus": {
"distribute": {
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\"/>"
]
}
}
}
}
样式设计
采用渐变背景和卡片式设计,提供良好的用户体验:
css
.container {
padding: 40rpx;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.btn {
width: 100%;
padding: 28rpx;
border-radius: 16rpx;
font-size: 32rpx;
text-align: center;
border: none;
color: white;
font-weight: bold;
}
技术要点总结
- 环境检测 :通过检查
plus对象是否存在来判断运行环境 - 错误处理:完整的 try-catch 机制确保应用稳定性
- 用户体验:实时操作日志和 Toast 提示
- 功能完善:支持多种通知类型(即时、延迟、自定义)
- 权限配置:正确配置 Android 通知权限
运行效果
实现后的应用具备以下功能:
- 发送即时系统通知
- 发送延迟通知(5秒后显示)
- 发送随机内容的自定义通知
- 一键清空所有通知
- 实时操作日志记录
- 通知点击事件处理
注意事项
- 此功能需要在真机环境中测试,模拟器可能无法正常使用推送功能
- 不同 Android 版本对通知权限的要求可能不同
- iOS 设备的通知机制与 Android 有所不同,需要额外配置
通过以上实现,我们成功解决了 Vue 3 兼容性问题,并实现了一个功能完整的 UniApp 全局通知系统。这个方案既保证了兼容性,又提供了良好的用户体验和可扩展性。