乐于分享
好东西不私藏

你开发的Uniapp应用页面跳转还只会傻傻的用uni.navigateTo?快来充充电吧!

你开发的Uniapp应用页面跳转还只会傻傻的用uni.navigateTo?快来充充电吧!

书接上篇,我们今天继续来学习一下 UniApp 如何实现页面跳转相关功能,包含了应用内普通页面跳转、tab页跳转、历史记录返回,应用外h5页面跳转、跳转其他小程序页面等等场景,以及常见的参数传递方式讲解,附带了完整的设计思路和源码示例,以及常见避坑指南和开发实践。

此系列文章将带领你从移动端跨平台开发入门到精通,如果你也喜欢关注APP、小程序、公众号、H5等等应用的开发,可以持续关注后续更新,避免错过宝贵的知识分享。

致开发者的忠告: AI编程盛行的今天,我们并不是不需要学习技术,而是更应该专研技术,拥有把控全局的架构设计思维才能在AI盛行的未来有立足之地。

言归正传,咱们今天继续来聊一个看似简单、实则暗藏玄机的话题(页面跳转):UniApp 里的“交通指挥大师”——让你的页面想去哪就去哪!

你可能会想:“跳转不就是uni.navigateTo吗?有啥好学的?”但等你真的开始写项目,就会遇到:

  • 从列表页跳到详情页,返回时列表页状态没了  

  • 跳 tabBar 页面结果白屏或报错  

  • 传参数时 +、&、= 等特殊字符神秘失踪  

  • 小程序跳小程序一脸懵  

  • 页面跳着跳着就卡死了(页面栈爆炸)  

  • 想返回并传数据给上一页,不知道怎么做  

  • 想“前进”到下一个页面,却发现没有类似 navigateForward 的方法  

今天我就带你把这些坑全填平,让你成为一个真正的“交通指挥官”,页面想去哪就去哪,还能全身而退。


一、UniApp 跳转全家福(8种姿势,各有各的使命)

我们先画个图,把这八兄弟认全:

核心口诀:  

  • 普通页面:navigateTo(保留) / redirectTo(替换)  

  • tab 页面:switchTab(必须用这个)  

  • 重启式:reLaunch(清空页面栈)  

  • 返回:navigateBack(可带 delta)  

  • 外跳:用平台特有 API 或组件  


二、详细解剖:每个跳转长什么样?用在哪儿?

1️⃣ uni.navigateTo —— 最常用的跳转

特点:保留当前页面,跳转到应用内的某个页面,可以使用 uni.navigateBack 返回页面栈:+1  

// 跳转到详情页,并传 iduni.navigateTo({url'/pages/detail/detail?id=123&name=张三'})

应用场景:  

  • 列表 → 详情页  

  • 首页 → 二级、三级页面  

  • 只要需要“返回”的地方  

注意:不能跳转到 tabBar 页面(会失败)。


2️⃣ uni.redirectTo —— 替换当前页

特点:关闭当前页面,跳转到应用内的某个页面,不可返回原页面页面栈:不变(替换当前)  

uni.redirectTo({url'/pages/login/login?redirect=1'})

应用场景:  

  • 登录成功后替换掉登录页,不让用户再回到登录页  

  • 表单提交后跳转成功页,并清除表单页  


3️⃣ uni.switchTab —— tabBar 专用跳转

特点:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面页面栈:清除非 tab 页面,保留 tab 页面栈  

uni.switchTab({url'/pages/index/index'// 必须是 tabBar 里配置过的页面})

应用场景:  

  • 从二级页面返回首页  

  • 从详情页跳转到“购物车”tab  

大坑不能传参switchTab 不支持 url 带参数,因为 tabBar 页面通常只会初始化一次,传参没意义。解决传参:用全局变量、vuex、storage 等(后面详细讲)。


4️⃣ uni.reLaunch —— 重启式跳转

特点:关闭所有页面,打开到应用内的某个页面。相当于重新启动 APP 到指定页页面栈:清空 → 目标页  

uni.reLaunch({url'/pages/index/index'})

应用场景:  

  • 退出登录后回到首页  

  • 切换账号后完全重置页面栈  

  • 从推送消息直接进入某个页面,且不希望有历史页  


5️⃣ uni.navigateBack —— 返回

特点:关闭当前页面,返回上一页面或多级页面。页面栈:-delta  返回深度数值,代表返回一级还是多级,可选参数,默认为1

// 返回上一页uni.navigateBack()// 返回两层uni.navigateBack({delta2})

应用场景:  

  • 手动返回  

  • 保存草稿后自动返回  


6️⃣ 跳转外部页面(H5/App)

H5 端:  

// 直接打开新页面(外链)window.location.href='https://www.baidu.com'// 或新窗口打开window.open('https://www.baidu.com')

App 端:  

// 使用 plus.runtime.openURL(仅 App)plus.runtime.openURL('https://www.baidu.com')// 或使用 web-view 组件内嵌

小程序内嵌 H5:使用 <web-view> 组件,src 指向外链即可。


7️⃣ 小程序跳转其他小程序 —— uni.navigateToMiniProgram

特点:微信小程序/支付宝小程序等平台支持。注意:需要目标小程序的 AppId,且必须在公众平台配置跳转名单(白名单)。

uni.navigateToMiniProgram({appId'wx1234567890',path'pages/index/index',success(res) {// 跳转成功  }})

三、页面传参的 N 种姿势(别再只会 URL 传参了!)

🔸 方式一:URL 传参(最常用,适合简单数据)

发送页:  

constparams= {id123,name'张三',from'list'}// 拼接成 id=123&name=张三&from=listletquery=Object.keys(params).map(key=>`${key}=${params[key]}`).join('&')uni.navigateTo({url`/pages/detail/detail?${query}`})

接收页(onLoad):  

onLoad(options) {console.log(options.id)    // '123'  注意:都是字符串!console.log(options.name)  // '张三'}

⚠️ 必坑指南:  

  1. 参数值默认字符串:数字类型记得 parseInt。  

  2. 特殊字符必须编码:如果参数值包含 &=?#/+、空格等,必须编码!  

constname=encodeURIComponent('张三&李四')uni.navigateTo({url`/pages/detail/detail?name=${name}`})// 接收时onLoad(options) {constrawName=decodeURIComponent(options.name// '张三&李四'}
  1. 数据量不宜过大:URL 长度有限制(小程序大约 2KB)。传递对象可先 JSON.stringify 再 encodeURIComponent:  

    constuser= { name'张三'age18 }constuserStr=encodeURIComponent(JSON.stringify(user))uni.navigateTo({url`/pages/detail/detail?user=${userStr}`})// 接收时onLoad(options) {constuser=JSON.parse(decodeURIComponent(options.user))}

🔸 方式二:全局事件总线(适合跨页面、返回传参)

特点:任意页面监听,任意页面触发,数据不下线。注意必须手动销毁监听,否则会造成内存泄漏。

发送页:  

// 触发事件,携带数据uni.$emit('updateUserInfo', { name'张三'age18 })uni.navigateBack()  // 返回上一页

接收页(通常在 onLoad 监听,onUnload 销毁):  

onLoad() {uni.$on('updateUserInfo', (data=> {console.log('收到更新:'data)this.userInfo=data  })}onUnload() {uni.$off('updateUserInfo')  // 必须清理}

适用场景:  

  • 从详情页编辑后返回列表页,刷新列表  

  • 从 A 页跳 B 页,B 页操作后把数据传回 A 页  


🔸 方式三:全局存储(Vuex / Pinia / uni.setStorageSync)

特点:持久化,适合全局状态(用户信息、购物车角标)。缺点:需要手动清理,不适合临时、一次性传参。

示例(使用 Storage)发送页:  

uni.setStorageSync('orderInfo', { orderId'12345' })uni.navigateTo({url'/pages/pay/pay'})

接收页:  

onShow() {constorderInfo=uni.getStorageSync('orderInfo')if (orderInfo) {// 使用数据uni.removeStorageSync('orderInfo'// 用完及时清理  }}

Vuex / Pinia 同理,跳转前 commit/action,目标页通过 computed 获取。


🔸 方式四:getCurrentPages() 直接操作上一页实例(黑科技,慎用)

特点:可以直接调用上一页的方法、修改上一页的数据。缺点:强耦合,不易维护,但在某些紧急场景可救急。

// 在目标页中constpages=getCurrentPages()constprevPage=pages[pages.length-2]  // 上一页实例// 如果上一页是 Vue 页面prevPage.$vm.setData({ name'张三' })    // 修改 dataprevPage.$vm.refreshList()               // 调用方法

适用场景:  

  • 返回上一页并刷新,且不想用事件总线的临时方案  

  • 但建议优先使用事件总线或 storage  


🔸 方式五:返回并传参 —— 利用 navigateBack 配合事件总线

这是最优雅的“返回传参”方案,上面在事件总线已讲。


四、历史记录返回与前进 —— 你真的懂页面栈吗?

📚 什么是页面栈?

UniApp(小程序/App)维护了一个页面栈(数组),记录了用户访问的页面路径。每次 navigateTo 会往栈里 push 一个新页面,navigateBack 会 pop 掉当前页面(可一次 pop 多个)。  

页面栈容量:微信小程序最多 10 层,超过会失败。如何查看当前页面栈:  

constpages=getCurrentPages()console.log('页面栈深度:'pages.length)console.log('当前页面:'pages[pages.length-1])console.log('上一页:'pages[pages.length-2])

🔹 返回(navigateBack)的更多细节

  • delta 默认是 1,表示返回一级。  

  • 如果 delta 大于页面栈长度,会回到首页(并抛出警告)。  

  • 返回时,被关闭的页面会触发 onUnload 生命周期。  

返回并刷新的最佳实践:  

// 在 A 页面监听事件onLoad() {uni.$on('refreshList', () => {this.getList()  })}onUnload() {uni.$off('refreshList')}// 在 B 页面操作完成后uni.$emit('refreshList')uni.navigateBack()

🔹 前进 —— 没有 navigateForward,怎么办?

误区:很多新手以为有 uni.navigateForward,其实没有。为什么?因为在小程序/App 环境中,页面栈是由用户行为驱动的,不支持“前进”到之前访问过的页面(不像浏览器有“前进按钮”)。  

模拟“前进”的方法:  

  1. 重新跳转:用 navigateTo 或 redirectTo 再次打开那个页面(会重新加载,不是恢复状态)。  

  2. 使用页面栈缓存:如果你只是希望用户从 A → B → C,然后从 C 返回 B,再“前进”到 C?  

    • 用户从 C 返回 B 后,C 页面已经被销毁。如果希望再回到 C,需要重新 navigateTo C 并恢复状态(通过 URL 传参或存储)。  

    • 没有浏览器那样的“前进”按钮,这是小程序/App 与 Web 的本质区别。  

H5 端特殊情况在 H5 端,uni.navigateTo 底层调用 history.pushState,浏览器会有历史记录,用户可以使用浏览器的前进按钮但 UniApp 没有提供直接控制浏览器前进的 API,只能依赖用户操作。  

如果你需要完全控制前进后退(比如自定义导航栏),可以使用 uni.navigateBack + 重新跳转的组合。


🔹 页面传参与历史记录的关系

  • 通过 URL 传参的页面,当用户返回再前进(H5 浏览器前进)时,参数会从 URL 中重新获取(onLoad 会再次执行)。  

  • 在非 H5 端,没有“前进”操作,所以不需要考虑。


五、常见翻车现场 & 急救方案(血泪经验)

💥 错误1:用 navigateTo 跳 tabBar 页面

现象:跳转后白屏或报错 can not navigateTo tabBar page原因:tabBar 页面不能通过 navigateTo/redirectTo 打开,必须用 switchTab解决方案:改用 uni.switchTab


💥 错误2:参数里带了 & 或 +,接收时被截断

现象?name=张&三 → 接收 { name: '张' }原因& 是 URL 参数分隔符,会被解析成两个参数。解决方案encodeURIComponent 编码,接收时 decodeURIComponent


💥 错误3:页面栈溢出(卡死)

现象:页面可以无限跳转,点返回要很多次才能退出,甚至卡死。原因:页面栈默认最多 10 层(微信小程序),超过 10 层再 navigateTo 会失败。解决方案:  

  • 适时使用 redirectTo 替换,而不是一直 navigateTo。  

  • 监听页面栈深度,若接近 10 层则改用 redirectTo 或 reLaunch。  

constpages=getCurrentPages()if (pages.length>8) {// 接近上限,使用 redirectTouni.redirectTo({ url })else {uni.navigateTo({ url })}

💥 错误4:switchTab 后想传参

现象:希望从详情页跳到首页并携带参数,但 switchTab 不支持。解决方案:  

  • 使用全局变量:详情页 uni.setStorageSync('fromDetail', true),首页在 onShow 里读取并清空。  

  • 使用事件总线:详情页 uni.$emit('switchTabParams', { id: 123 }),首页监听(注意在 onUnload 移除)。  


💥 错误5:小程序跳其他小程序失败

现象navigateToMiniProgram 报错 appId 未配置原因:微信小程序后台必须配置“跳转其他小程序”的白名单。解决方案:  

  1. 登录微信公众平台 → 开发 → 开发设置 → 小程序跳转 → 添加目标小程序 AppId。  

  2. 测试时可以用体验版,但正式版必须配置。  

  3. 若无需返回原小程序,可使用 reLaunch 跳其他小程序(但依然需要白名单)。


💥 错误6:navigateBack 返回到 tab 页面,但 tab 页面不刷新

现象:从 tab A 页面跳到二级页面,做了修改,返回到 tab A 页面时,数据还是旧的。原因:tab 页面被缓存,返回时不会触发 onLoad,只会触发 onShow解决方案:把数据刷新的逻辑写在 onShow 里。


💥 错误7:H5 端 uni.navigateTo 导致浏览器历史记录混乱

现象:用户点击返回按钮,可能会跳出你的网页。原因:H5 端 navigateTo 默认调用 pushState,但浏览器的返回行为可能与预期不同。解决方案:  

  • 在 H5 端,如果希望自定义返回行为,可以使用 uni.webView 或直接 location.href。  

  • 或者监听 popstate 事件做拦截。


💥 错误8:uni.$on 监听后未销毁,导致重复执行

现象:页面来回切换几次,事件触发了多次。原因uni.$on 是全局监听,页面卸载时未 uni.$off,再次进入页面时会再绑定一次,导致多个监听共存。解决方案成对出现:在 onLoad 监听,onUnload 移除。


💥 错误9:使用 getCurrentPages() 操作上一页,但上一页已销毁

现象:从 A → B → C,在 C 中获取上一页是 B,没问题。但如果从 B 返回 A 后,B 已销毁,在 A 中获取上一页会得到 undefined 或错误实例。原因:页面栈动态变化,已卸载的页面实例不应再操作。解决方案:操作前判断实例是否存在,或改用其他传参方式。


六、选型决策树:到底用哪个跳转?


七、一道送命题,考考你

场景:用户在商品详情页,点击“购买”按钮,跳转到订单确认页,提交订单后跳转到支付页,支付成功后回到“我的”tab 页面。问:整个流程分别用了哪些跳转方法?

答案:  

  1. 详情页 → 订单确认页:uni.navigateTo(需要返回详情页)  

  2. 订单确认页 → 支付页:uni.redirectTo(提交后不应再返回订单确认页)  

  3. 支付成功页 → “我的”tab:uni.switchTab(tab 页面专用)  

如果你答对了,说明你已经出师了 👍


八、最后再交代两句

小老弟,页面跳转是 UniApp 里最基础、但也最容易出错的模块之一。记住一点:用对方法,比用酷炫的方法更重要。

  • 跳 tab 用 switchTab

  • 普通跳转用 navigateTo

  • 不想让用户返回用 redirectTo

  • 传参记得 encodeURIComponent

  • 页面栈别塞太满  

  • 返回传参用事件总线  

  • 没有“前进”API,自己模拟重新跳转  

你可以在项目里打开开发者工具的 “页面栈” 面板(小程序开发者工具 → AppData 旁),亲眼看看每次跳转栈的变化,印象会更深。

好了,去把你项目里的跳转逻辑检查一遍,有则改之无则加勉。遇到玄学报错,先看看是不是跳错了方法,或者参数没编码。

下次见!—— 一个被页面栈溢出折磨过无数次的过来人 !

加油,未来的全栈大佬!💪如果你也对移动端跨端开发感兴趣,关注我,后续还有更多优质文章分享!

往期相关文章推荐

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 你开发的Uniapp应用页面跳转还只会傻傻的用uni.navigateTo?快来充充电吧!

评论 抢沙发

8 + 9 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮