plus.push.addeventlistener('click', ) 是唯一可靠入口,需在 main.js 或根组件 created 钩子中尽早注册;ios payload 为对象、android 为字符串,须统一解析并加 try/catch;跳转前需 settimeout(300ms) 确保路由就绪,且路径须为 pages.json 中注册的相对路径。

plus.push.addEventListener('click', ) 是唯一可靠入口
App 被杀死后用户点击通知栏,onLaunch 和 onShow 基本收不到 payload:Android 完全不透传,iOS 热启动时 options.push 为空。系统原生层(Android Intent / iOS application:didReceiveRemoteNotification:fetchCompletionHandler:)把数据交给了 plus.push 模块,而不是 Vue 生命周期。必须在 App 启动早期(如 main.js 或根组件 created 钩子)注册监听,否则错过事件。
iOS 和 Android 的 msg.payload 类型不一致
直接 JSON.parse(msg.payload) 在 iOS 上会报错,因为 iOS 的 msg.payload 是已解析的对象;Android 则是原始字符串。华为、小米等厂商通道还可能把真实 payload 塞进 msg.extra 或 msg.intent,不能只认 payload 字段。
- 统一解包写法:
const payload = msg.payload ? (typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload) : {}; - 华为通道建议额外检查:
msg.extra && typeof msg.extra === 'string' ? JSON.parse(msg.extra) : {} - 务必加
try/catch,避免解析失败导致整个 click 回调中断
跳转前必须延迟并校验路由
uni.navigateTo 在 push 回调里直接调用大概率白屏——此时 Vue 实例、路由系统、uni API 尚未就绪。也不能依赖 uni.getSystemInfoSync() 等判断是否 ready,最稳的是用 setTimeout 等待。
- 最小安全延迟:300ms,写成
setTimeout(() => { uni.navigateTo({ url }) }, 300) - 路径必须是相对路径,不带
.vue后缀,且已在pages.json的pages数组中注册 - 若目标是 tabBar 页面(如
pages/index/index),必须改用uni.switchTab,navigateTo会静默失败或报错 - 防重复:同一离线通知可能触发多次 click(尤其厂商通道),建议用
uni.setStorageSync('last_push_payload', payload)缓存,进入首页后再清空
跳转失败时没有明显提示,白屏是常态
uni-app 不会在控制台主动报“页面未找到”,而是静默渲染空白页。常见原因包括路径大小写错误(Pages ≠ pages)、多写了开头斜杠(/pages/a/a 应为 pages/a/a)、目标页尚未注册或拼写遗漏。
- 强制加
fail回调:uni.navigateTo({ url, fail: err => console.error('push跳转失败', url, err) }) - H5 平台不支持 push 通知,该逻辑需用
process.env.UNI_PLATFORM === 'app'包裹 - 真机调试务必关掉「后台暂停脚本」(iOS 设置 → 通用 → 后台App刷新 → 关),否则热启动时监听器失效
msg.extra 的非标处理和 iOS 热启动下监听器注册时机——哪怕只晚注册 100ms,就可能收不到 click 事件。











