← 返回题目列表

小程序有哪些页面跳转方式?它们有什么区别?

高频 中等 第 13 / 32 题 更新于 2026/07/28
小程序路由页面栈

简化版

小程序常见跳转方式有 navigateToredirectToswitchTabreLaunchnavigateBack。核心区别在于是否保留当前页面、是否能跳 tabBar 页面、是否清空页面栈。理解页面栈是回答这类问题的关键。

详细版

常见 API:

  • navigateTo:保留当前页面,跳到非 tabBar 页面。
  • redirectTo:关闭当前页面,跳到非 tabBar 页面。
  • switchTab:跳到 tabBar 页面,并关闭其他非 tabBar 页面。
  • reLaunch:关闭所有页面,打开指定页面。
  • navigateBack:返回上一页或多级页面。

页面栈决定了返回行为。navigateTo 会增加页面栈层级,所以可以返回;redirectTo 替换当前页,不能返回被替换页面;reLaunch 清空栈,适合登录后进入首页或退出后回登录页。

完整版教学

一、页面栈是什么

小程序维护一个页面栈,用户每打开一个新页面,就可能往栈里压入一个页面。返回时从栈顶弹出当前页面,露出上一个页面。

理解页面栈后,跳转 API 就不难了。它们本质上是在控制页面栈怎么变化。

二、常见跳转 API 对比

navigateTo 是最常用的普通跳转方式。它会保留当前页面,再打开新页面。适合从列表进入详情,因为用户通常需要返回列表。

redirectTo 会关闭当前页面,再打开新页面。适合流程页替换,比如提交成功页不希望用户返回提交表单。

switchTab 专门用于跳转 tabBar 页面。普通跳转 API 不能直接跳 tabBar 页面。

reLaunch 会清空所有页面并打开新页面。适合重置应用状态,比如退出登录后进入登录页。

navigateBack 用来返回,支持通过 delta 指定返回层级。

三、常见错误

很多问题来自混用跳转 API:

  • navigateTo 跳 tabBar 页面会失败。
  • redirectTo 后发现返回不了上一页,这是正常的,因为当前页被替换了。
  • 流程页一直 navigateTo,导致页面栈越来越深。
  • 登录态失效时只 navigateBack,可能回到不该访问的页面。

四、面试追问与工程落地

面试官可能问:“登录成功后应该用什么跳转?”

如果登录页不希望用户返回,通常用 redirectToreLaunch。如果要进入 tabBar 首页,则使用 switchTabreLaunch。如果要清理历史页面,优先 reLaunch

工程中可以封装统一路由方法,把登录校验、参数序列化、异常提示、tabBar 判断集中处理,减少页面中散落大量 wx.navigateTo

五、用页面栈推演 API

用 A、B、C 三个页面推演最直观:A navigateTo B 后栈为 [A, B],B 再打开 C 为 [A, B, C];C navigateBack({ delta: 2 }) 后回到 A。若 B 使用 redirectTo C,则 [A, B] 变为 [A, C],B 已卸载,无法再返回。

API栈变化示例tabBar 目标典型场景
navigateTo[A] → [A,B]不可列表进入详情
redirectTo[A,B] → [A,C]不可流程当前步骤替换
navigateBack[A,B,C] → [A]不涉及返回一层或多层
switchTab切到指定 tab,关闭其他非 tab 页必须进入主导航页
reLaunch[...] → [T]登录失效、全局重置

小程序页面栈存在层数上限,常见文档口径是最多 10 层;连续 navigateTo 的流程应在接近上限前改用替换、返回或重构导航。不要把这个限制当业务分页计数,而要从交互上避免用户钻进无法理解的深栈。

六、参数、返回通信与状态恢复

URL 查询参数适合小而稳定的标识,例如经过编码的 id=42,不适合塞完整 JSON、敏感信息或权威价格。目标页在 onLoad(options) 读取参数后仍要请求或校验最新数据,因为路由参数可被构造,也可能在页面驻留期间过期。

navigateTo 可通过 events 与成功回调中的 eventChannel 在打开页和被打开页之间传递一次性结果。例如选择地址页返回 { addressId: 7 },原页面收到后重新查询地址;这比获取 getCurrentPages() 后直接修改上一页实例更清晰。

wx.navigateTo({
  url: '/pages/address/select',
  events: {
    selected({ addressId }) {
      reloadAddress(addressId)
    }
  }
})
// 选择页:this.getOpenerEventChannel().emit('selected', { addressId: 7 })

跨页面长期共享状态再使用 store 或服务端,不要让 EventChannel 变成全局总线。

tabBar 页面可能已经存在,switchTab 后通常触发其 onShow 而不是重新 onLoad。路由封装应处理 tabBar 白名单、参数编码、失败回调和登录重定向,并防止登录页自身再次触发登录重定向形成循环。

记忆钩子:先画栈再选 API——要“压栈返回”用 navigate,要“替换当前”用 redirect,要“清空重来”用 reLaunch。

七、常见误区与追问

  • 误区:navigateTo 可以打开任意页面,包括 tabBar 页面。 tabBar 页面应使用 switchTab,普通压栈 API 不适用。
  • 误区:redirectTo 会清空整个页面栈。 它只替换当前页;清空并建立新根页面的是 reLaunch
  • 误区:页面参数来自自己代码,所以服务端可以直接信任。 路径可以被分享或构造,身份、金额和资源权限仍要由服务端校验。
  • 追问:登录成功后选 redirectTo 还是 reLaunch 只替换登录页可用 redirect;需要清除所有受保护历史页时用 reLaunch;目标是 tabBar 且无需清栈可 switchTab。
  • 追问:详情页返回列表如何带回刷新结果? 可用 EventChannel 返回最小结果,或让列表在 onShow 按脏标记重新请求。
  • 追问:为什么不建议直接修改 getCurrentPages() 中上一页的数据? 它耦合页面实现和栈结构,绕过明确通信契约,重构与异常路由时容易失效。
  • 追问:如何避免页面栈过深? 流程完成后 redirect/reLaunch,能返回已有页时 navigateBack,并在统一路由层监控栈深。

八、加强记忆

路由 API 不靠死背,画页面栈即可:navigateTo 压栈并保留返回,redirectTo 替换栈顶,navigateBack 弹栈,switchTab 进入 tabBar,reLaunch 清栈重建。参数只传最小标识,返回结果用 EventChannel 或可见时刷新;业务权威状态由服务端维护,并始终防止深栈和重定向循环。