冷启动跳转失败主因是监听器未在app.vue的onlaunch中注册,必须在此处注册并延迟执行uni.navigateto、json.parse msg.payload且判空、处理厂商差异、引导用户开启自启动等权限。

plus.push.addEventListener("click") 必须在 App.vue 的 onLaunch 中注册
冷启动时监听器没挂载,点击通知就彻底丢失事件——这是 80% 线上跳转失败的根源。onLaunch 是唯一能确保监听器在 App 启动第一毫秒就就位的时机。
常见错误现象:console.log 完全没输出、热启动能触发但冷启动静默失败、华为手机点通知黑屏。
- 不能放在某个页面的
onLoad或mounted中——用户点通知时页面根本没加载 - 不要在
onShow里重复注册——可能触发多次回调,导致重复跳转或路由报错 - HBuilderX 3.5.1+ 和 UniPush 2.0 仍强制依赖该写法,无替代方案
msg.payload 是字符串,不是对象,必须 JSON.parse 且判空
iOS 和 Android 都把业务数据塞进 msg.payload,但它默认是字符串,直接访问 msg.payload.id 会报 Cannot read property 'id' of undefined。
厂商通道差异明显:小米/OPPO 可能把 payload 打包进 msg.extra;华为 EMUI 12+ 甚至返回空字符串或 "{}"。
- 必须加
try { JSON.parse(msg.payload) } catch (e) { } - 优先检查
msg.extra,再 fallback 到msg.payload - 对
msg.payload === ""或JSON.stringify(payload) === "{}"做兜底处理
uni.navigateTo 在 click 回调里直接调用会失败
plus.push 的 click 回调发生在原生层,此时 Vue 实例可能尚未初始化完成,uni.navigateTo 会静默失败或抛出 no page 错误。
这不是 bug,是生命周期错位——你试图在 App 还没“活过来”时让它导航。
- 正确做法:把跳转逻辑封装成函数,用
setTimeout延迟 300ms 再执行 - 更稳妥方案:将 payload 存入
uni.setStorageSync('pending_push'),在首页onLoad中读取并跳转 - 电商类应用建议服务端同步记录一条「待跳转 cid + payload」,App 启动后主动拉取一次,避免前端丢失
华为手机点通知黑屏,不是代码问题,是权限链断裂
即使监听注册成功、payload 解析无误,华为(尤其 EMUI 12+ / HarmonyOS 4.0+)仍大概率不触发 click 回调——系统杀死了 push 进程,通知栏消息只是“幻影”。
表现是:有通知、能展示、点击后黑屏或直接回到桌面,console.log 完全不打印。
- 必须手动引导用户开启「自启动」「电池优化白名单」「通知使用权」
- 不能只靠 JS 提示,需调用
plus.android.requestPermissions触发系统弹窗 - 部分机型需额外适配 HMS Core 推送 SDK,仅靠 UniPush 默认通道不可靠
冷启动跳转这件事,从来不是写对一行 plus.push.addEventListener 就能搞定的。payload 解析、路由延迟、厂商权限、服务端兜底,四者缺一不可——漏掉任意一环,用户点通知就等于点了空气。











