做小程序开发,页面跳转和参数传递是再日常不过的操作。乍一看,这事儿无非就是拼个 URL 字符串,然后在目标页面接收一下。可真到了复杂的业务场景里,各种边界情况和框架自带的限制,往往能让人踩不少坑。今天咱们就结合实际开发场景,把小程序传参这些大大小小的细节彻底捋顺。
先说最基础的普通页面跳转。假设你要从商品列表跳到详情页,需要带上商品 ID 和来源标识。用 wx.navigateTo 时,直接在 URL 后面拼接参数就行:

wx.navigateTo({
url: '/pages/detail/detail?itemId=1001&source=home'
})
到了目标页面,在
onLoad 生命周期里就能直接拿到这些值:onLoad(options) {
console.log(options.itemId); // 输出 1001
console.log(options.source); // 输出 home
// 接着就可以用 itemId 去请求详情接口了
}

如果你习惯用
<navigator> 组件,思路也一样,在 url 属性里拼好参数即可。这种简单的键值对传递,基本不会出什么岔子。
但业务一复杂,我们要传的数据往往不是简单的字符串,而是多层嵌套的复杂对象。很多新手会想当然地把对象直接塞进 URL,结果到了目标页面一打印,全变成了
[object Object]。要知道,URL 参数本质上只能是字符串。想传复杂对象,必须先做序列化和编码。发送前,先用
JSON.stringify 转成字符串,再用 encodeURIComponent 编码:const params = { id: 1, tags: ['hot', 'new'] };
const url = /pages/detail/detail?data=${encodeURIComponent(JSON.stringify(params))};
wx.navigateTo({ url });
接收时,记得做反向操作,先解码再解析:
onLoad(options) {
if (options.data) {
const params = JSON.parse(decodeURIComponent(options.data));
console.log(params.tags); // 输出 ['hot', 'new']
}
}
不过,如果对象实在太大,拼在 URL 里不仅看着眼晕,还容易超出长度限制。遇到这种情况,更推荐把数据存到全局变量(
getApp().globalData)、本地缓存(wx.setStorageSync),或者使用微信官方提供的 EventChannel 进行页面通信,代码写起来会优雅得多。聊完普通页面,必须提一个极易踩坑的特殊场景:跳转到底部的 TabBar 页面。

在原生微信小程序里,跳 TabBar 页面必须用
wx.switchTab,而这个 API 压根不支持在 URL 里带参数。如果你硬拼了参数过去,目标页面的 onLoad 里是绝对拿不到的。那怎么给 TabBar 传参?通常只能绕个弯:要么跳转前把参数存进
getApp().globalData,目标页面再去读;要么用本地缓存,跳过去之后取出来,用完记得清理掉。这里多说一句,如果你用的是 uni-app 这类跨端框架,框架底层可能做了一些 Hack 处理,允许你直接传参。但在写原生小程序时,千万别想当然,一定要老老实实遵守官方的限制。顺利拿到参数只是第一步,真正的考验在于后续的业务处理。在真实的项目里,永远不要假设参数一定会完美传过来。用户完全可能通过扫码、点击分享卡片等外部途径直接进入页面,这时候
options 里的参数大概率是空的。因此,在
onLoad 里一定要做好参数校验和兜底逻辑。比如,判断核心参数是否存在;如果缺失,是展示默认内容、弹出错误提示,还是直接 wx.navigateBack 返回上一页?把这些异常分支处理妥当,小程序的交互体验才会显得真正专业和健壮。页面跳转传参看似是个基础操作,但细节里往往藏着魔鬼。从基础的字符串拼接,到复杂对象的编码转换,再到 TabBar 页面的特殊处理和异常兜底,把这些场景都摸透了,写出来的代码自然会更稳健,小程序的页面交互也会更加丝滑。
今すぐログイン