UniApp 全局通知功能实现

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;
}

技术要点总结

  1. 环境检测 :通过检查 plus 对象是否存在来判断运行环境
  2. 错误处理:完整的 try-catch 机制确保应用稳定性
  3. 用户体验:实时操作日志和 Toast 提示
  4. 功能完善:支持多种通知类型(即时、延迟、自定义)
  5. 权限配置:正确配置 Android 通知权限

运行效果

实现后的应用具备以下功能:

  • 发送即时系统通知
  • 发送延迟通知(5秒后显示)
  • 发送随机内容的自定义通知
  • 一键清空所有通知
  • 实时操作日志记录
  • 通知点击事件处理

注意事项

  1. 此功能需要在真机环境中测试,模拟器可能无法正常使用推送功能
  2. 不同 Android 版本对通知权限的要求可能不同
  3. iOS 设备的通知机制与 Android 有所不同,需要额外配置

通过以上实现,我们成功解决了 Vue 3 兼容性问题,并实现了一个功能完整的 UniApp 全局通知系统。这个方案既保证了兼容性,又提供了良好的用户体验和可扩展性。

相关推荐
华玥作者19 小时前
[特殊字符] VitePress 对接 Algolia AI 问答(DocSearch + AI Search)完整实战(下)
前端·人工智能·ai
Mr Xu_19 小时前
告别冗长 switch-case:Vue 项目中基于映射表的优雅路由数据匹配方案
前端·javascript·vue.js
前端摸鱼匠19 小时前
Vue 3 的toRefs保持响应性:讲解toRefs在解构响应式对象时的作用
前端·javascript·vue.js·前端框架·ecmascript
lang2015092819 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
好家伙VCC20 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
未来之窗软件服务21 小时前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君
嘿起屁儿整21 小时前
面试点(网络层面)
前端·网络
VT.馒头21 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
phltxy1 天前
Vue 核心特性实战指南:指令、样式绑定、计算属性与侦听器
前端·javascript·vue.js
Byron07071 天前
Vue 中使用 Tiptap 富文本编辑器的完整指南
前端·javascript·vue.js