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 全局通知系统。这个方案既保证了兼容性,又提供了良好的用户体验和可扩展性。

相关推荐
醉城夜风~16 分钟前
CSS元素显示模式(display)
前端·css
AI大模型-小华1 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子3 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅3 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni4 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学5 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
赵庆明老师5 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim
wc886 小时前
微软EDGE浏览器功能学习
前端·学习·edge
Csvn6 小时前
🎯 原生 `<dialog>` 元素:终于可以扔掉一半的自定义弹窗组件了?
前端