plus.push.addEventListener('click') 必须在 App.vue 的 onLaunch 中注册,确保冷启动时监听器最早且仅一次挂载;payload 解析需兼容双端差异并做类型判断与容错;跳转前须校验 target_page 并 fallback,tabBar 页面必须用 uni.switchTab。

plus.push.addEventListener('click') 必须在 App.vue 的 onLaunch 里注册
冷启动时监听器没挂上,点击通知就彻底丢失事件。真机上常见现象是:通知栏有消息,点完黑屏或回到桌面,控制台连 console.log 都没有——不是代码写错了,是监听器根本没注册上。
别在某个页面的 onLoad 或 mounted 里注册,App 还没加载到那个页面,用户已经点进来了。也别在 onShow 里重复注册,会导致多次触发跳转。
-
onLaunch是唯一能确保监听器「最早、只一次」挂载的时机 - HBuilderX 3.5.1+(UniPush 2.0)仍强制依赖此机制,无替代方案
- 如果用了自定义基座,确认 manifest.json 中已开启
Push插件
msg.payload 结构双端不一致,必须做类型判断和容错解析
iOS 和 Android 的 msg.payload 类型、内容、甚至字段名都不同。直接 msg.payload.type 会报 Cannot read property 'type' of undefined,因为 payload 可能是字符串、空对象、空字符串,甚至根本不存在。
华为/小米等厂商通道还可能把业务数据塞进 msg.extra 或 msg.intent,不能只盯 payload 一个字段。
- 统一处理逻辑:
const payload = msg.payload ? (typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload) : {} - 华为 EMUI 12+ 和小米 HyperOS 下,冷启动时
msg对象可能为空,需 fallback 到本地缓存(如uni.getStorageSync('last_push')) - 服务端推送时务必确保
content-available=1(iOS 静默唤醒)或启用透传模式,否则 payload 不会下发
分类跳转不能只靠 payload 字段,得结合 type + target_page + 业务兜底
单纯用 payload.type 做 if-else 分支容易漏场景。比如订单更新、客服消息、系统公告共用 type: "notification",但跳转路径完全不同;或者用户点了通知却没网络,payload 拿不到,跳转就卡死。
真实线上环境里,跳转失败往往不是因为路由写错,而是 payload 缺失或结构异常后没 fallback 路径。
- 推荐 payload 至少包含三个字段:
type(业务类型)、target_page(完整路径)、params(查询参数对象) - 跳转前加校验:
if (!payload.target_page) { uni.navigateTo({ url: '/pages/home' }); return; } - 冷启动时若 payload 无效,查本地缓存的
cid+ 后端记录匹配最近一条待跳转任务,避免白屏
tabBar 页面跳转要用 uni.switchTab,普通页面才用 uni.navigateTo
在 plus.push.addEventListener('click') 回调里直接调 uni.navigateTo 会失败——此时 Vue 实例还没 ready,uni API 尚未注入,控制台报 undefined is not a function。
更隐蔽的问题是:跳转到 tabBar 页面却用了 navigateTo,结果页面白屏或路由栈混乱,用户再点 tab 会重复加载。
- 跳转 tabBar 页面(如
/pages/index/index)必须用uni.switchTab({ url: '...' }) - 跳转非 tabBar 页面(如
/pages/order/detail)用uni.navigateTo({ url: '...', fail: () => uni.reLaunch({ url: '/pages/home' }) }) - 所有跳转建议包一层
setTimeout(() => { ... }, 100),给 Vue 初始化留出缓冲时间


















