url传参需encodeuricomponent(json.stringify(obj))且接收页用decodeuricomponent+json.parse处理;超2kb易截断;eventchannel适合父子页安全传对象;vuex/pinia管多页共享状态;避免$eventbus防内存泄漏。

URL传参带对象:用JSON.stringify但必须encodeURIComponent
直接把对象拼进 URL 是最常见做法,但不加处理会出错——比如对象里有空格、斜杠、中文,uni.navigateTo 会截断或解析失败。正确写法是先序列化再编码:
uni.navigateTo({ url: `/pages/detail/detail?user=${encodeURIComponent(JSON.stringify(userInfo))}` })- 接收页
onLoad(options)中必须用decodeURIComponent+JSON.parse双重处理,缺一不可 - URL 总长度不能超约 2KB,含域名和路径;传大对象(如商品详情含图片数组)大概率被截断,此时控制台无报错,
options.user可能是空字符串或不完整 JSON
用eventChannel传对象:适合父子页单向强关联场景
这是 uni-app 官方推荐的「安全通道」,专为页面跳转时传复杂数据设计,不走 URL,无长度限制,且天然支持双向通信。
- 跳转时创建通道:
uni.navigateTo({ url: '/pages/detail/detail', events: { onUserInfoReady: (data) => console.log(data) } }) - 目标页通过
this.getOpenerEventChannel()发送或监听:eventChannel.emit('onUserInfoReady', userInfo) - 注意:
eventChannel只在「子页由父页跳转打开」时有效;如果是uni.reLaunch或从 TabBar 进入,getOpenerEventChannel()返回null - 不支持跨多层跳转(比如 A→B→C,C 想回传给 A),只能用于直接打开者与被打开者之间
全局状态管理(Vuex/Pinia):适合需要多页共享+持久化场景
如果你的参数要被 3 个以上页面读取,或需在页面卸载后仍保留(比如用户登录态、筛选条件),别硬塞 URL,直接进 store。
- 传参本质是
store.commit('setUser', userInfo),接收页用mapState或useStore().state.user读取 - 优势在于响应式:一处改,所有绑定该 state 的页面自动更新
- 坑点:如果只是临时跳转用一次的数据(比如订单预览页传一个待提交对象),放进 Vuex 会造成冗余状态,增加调试难度
- PINIA 在 H5 和小程序端行为一致;Vuex 在某些旧版微信小程序基础库中存在兼容问题,建议新项目优先 PINIA
避免用$eventBus传参:内存泄漏风险高且调试困难
虽然网上很多教程教你在 main.js 挂一个 Vue.prototype.$eventBus = new Vue(),但实际项目中它是最容易翻车的方式。
- 监听未及时
$off会导致事件堆积,同一操作触发多次回调;onUnload里漏写移除逻辑是常态 - 事件名冲突难发现(比如两个页面都
$emit('update')),没有类型提示,IDE 无法跳转定义 - uni-app 的页面实例销毁机制和 Vue 组件不完全一致,
$eventBus在 App.vue 或 tab 页面中尤其容易失活 - 真要用事件通信,优先选
uni.$emit+uni.$on,至少生命周期更可控;但依然不如eventChannel或 store 直观
真正关键的不是“有多少种方式”,而是哪种方式让下个月你自己看代码时能立刻明白数据从哪来、到哪去、会不会残留。URL 传简单值,eventChannel 传跳转上下文,store 管跨页面状态——边界划清楚,比堆技巧重要得多。










