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 小时前
状态管理大乱斗#05 | Riverpod 源码评析 (中) - 上层建筑
android·前端·flutter
土豆125019 小时前
Rust 生命周期开发实战:从"编译不过"到"一次过编"的实用指南
前端·rust
candyTong1 天前
一觉醒来,大模型就帮我排查完页面性能问题
前端·javascript·架构
魔术师Grace1 天前
我给 AI 做了场入职培训
前端·程序员
玩嵌入式的菜鸡1 天前
网页访问单片机设备---基于mqtt
前端·javascript·css
前端一小卒1 天前
我用 Claude Code 的 Superpowers 技能链写了个服务,部署前差点把服务器搞炸
前端·javascript·后端
滑雪的企鹅.1 天前
HTML头部元信息避坑指南大纲
前端·html
一拳不是超人1 天前
老婆天天吵吵要买塔罗牌,我直接用 AI 2 小时写了个在线塔罗牌
前端·ai编程
阿丰资源1 天前
SpringBoot+Vue实战:打造企业级在线文档管理系统
vue.js·spring boot·后端