必须在App.vue的onLaunch中第一时间注册plus.push.addEventListener('click', ...),否则真机冷启动时监听器未挂载将永久丢失离线点击事件;需判别msg.payload类型并JSON.parse,加setTimeout延迟跳转,且90%问题源于厂商通道配置错误而非代码。

必须在 App.vue 的 onLaunch 中第一时间注册 plus.push.addEventListener('click', ...),否则真机上完全收不到离线点击事件。这不是逻辑问题,是原生层事件丢失——App 被杀后 JS 上下文不存在,监听器没挂载就永远错过。
为什么 onLaunch/onShow 拿不到 payload
iOS 热启动或 Android 全场景下,onLaunch 和 onShow 的 options 参数里 push 字段为空。系统根本不会把通知点击携带的原始数据(Android Intent extras / iOS application:didReceiveRemoteNotification:fetchCompletionHandler:)透传给 Vue 生命周期钩子。uni-app 封装层默认跳过了这一步,你得自己伸手去接。
plus.push.addEventListener('click') 必须写在 onLaunch 里
监听器必须在 App 启动最早期挂载,早于任何页面加载、路由初始化或 store 初始化。放在某个页面的 onLoad 或 mounted 里,冷启动时根本不会执行到那一步。
-
plus.push.addEventListener('click', callback)的第二个参数false不能省略(虽然文档没强调,但部分基座版本不传会失效) - 回调里必须先判断
msg.type === 'click',因为同一监听器也会触发receive事件 - iOS 的
msg.payload是对象,Android 的msg.payload多为字符串,需做typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload - 不要在回调里直接调用
uni.navigateTo,可能因页面栈未就绪而失败;建议用setTimeout(() => { /* 跳转 */ }, 100)或存入全局状态后由首页读取
离线收不到?先查厂商通道,不是代码问题
90% 的“点击无响应”或“拉不起 App”不是监听写错了,而是厂商通道没通。UniPush 在离线时自动降级走华为、小米、OPPO 等系统级服务,如果 manifest.json 里没配对应厂商的 appid、key,或云端打包没勾选对应通道,消息压根发不到手机系统层。
- Android:检查
manifest.json → app-plus → distribute → google-services.json是否存在(Google 通道),以及各厂商通道配置项是否填全 - iOS:确认
manifest.json → app-plus → distribute → ios → push下启用了 APNs,并上传了有效的 p8 推送证书 - 真机测试务必用自定义基座,标准基座不带厂商 SDK
- 可用
plus.push.getClientInfo()查 clientid 是否获取成功,为空说明推送 SDK 初始化失败
最容易被忽略的是:iOS 用户手动关闭通知权限后,连通知栏都不会显示,更别说点击拉起了;而 Android 厂商 ROM(如 MIUI、EMUI)可能默认冻结推送服务,需要用户手动开启「自启动」「电池优化豁免」——这些都不是代码能绕过的。











