微信小程序页面路由管理

官方文档

页面栈

框架以栈的形式维护了当前的所有页面。当发生路由切换的时候,页面栈的表现如下:

路由方式 页面栈表现
初始化 新页面入栈
打开新页面 新页面入栈
页面重定向 当前页面出栈,新页面入栈
页面返回 页面不断出栈,直到目标返回页,新页面入栈
Tab 切换 页面全部出栈,只留下新的 Tab 页面
重加载 页面全部出栈,只留下新的页面

getCurrentPages()

getCurrentPages()函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。
Tip:不要尝试修改页面栈,会导致路由以及页面状态错误。

路由方式

对于路由的触发方式以及页面生命周期函数如下:

路由方式 触发时机 路由前页面 路由后页面
初始化 小程序打开的第一个页面 onLoad, onSHow
打开新页面 调用 API wx.navigateTo 或使用组件 onHide onLoad, onShow
页面重定向 调用 API wx.redirectTo 或使用组件 onUnload onLoad, onShow
页面返回 调用 API wx.navigateBack 或使用组件或用户按左上角返回按钮 onUnload onShow
Tab 切换 调用 API wx.switchTab 或使用组件 或用户切换 Tab 各种情况请参考下表
重启动 调用 API wx.reLaunch 或使用组件 onUnload onLoad, onShow

Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):

当前页面 路由后页面 触发的生命周期(按顺序)
A A Nothing happend
A B A.onHide(), B.onLoad(), B.onShow()
A B(再次打开) A.onHide(), B.onShow()
C A C.onUnload(), A.onShow()
C B C.onUnload(), B.onLoad(), B.onShow()
D B D.onUnload(), C.onUnload(), B.onLoad(), B.onShow()
D(从转发进入) A D.onUnload(), A.onLoad(), A.onShow()
D(从转发进入) B D.onUnload(), B.onLoad(), B.onShow()

Tips:

  • navigateTo,redirectTo只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 调用页面路由带的参数可以在目标页面的onLoad中获取。

微信小程序路由栈不能超过 10 的解决方案

  • 小程序历史栈最多只支持10层
  • 当小程序业务比较复杂时,就很容易超过10层。
  • 当超过10层后,有的机型是点击无反应,有的机型会出现一些未知错误

方案一:最粗暴…navigateTo不行,那就redirectTo

小程序c路由跳转的方式有五种,分别是wx.navigateTo(打开新页面,新页面入栈)、wx.redirectTo(重定向,当前页面出栈,新页面入栈)、wx.navigateBack(返回,页面不断出栈,直到目标返回页)、wx.switchTab(切换tab页面,页面全部出栈,只留下新的 Tab 页面)、wx.reLaunch(页面全部出栈,只留下新的页面)
由此产生了第一种方式,当页面栈超过 10 时,直接用redirectTo
但这样太粗暴了,显然很多场景是需要保留访问过的页面的,由此有了方案一的升级版

方案二:在小程序页面栈之外维护多一个自己的逻辑栈

几个关键点:

  1. 9层(含9层)以内时:走小程序自己的历史栈就ok了,跳转时候更新一下逻辑栈,这没啥可说的
  2. 从9层跳转10层:需要把第9层重定向到中转页,再由中转页跳转到10层
  3. 10层以后跳转:在navigateTo方法中处理,到10层之后,再跳转就第10层页面一直做redirectTo(重定向)操作了
  4. 10层以上返回:会返回到中转页,由中转页判断,具体返回到哪个页面,然后navigateTo(跳转)过去
  5. 从10层返回到9层:返回到中转页,将中转页redirectTo(重定向)到第9层页面
  6. 9层内的返回:直接返回就好了,返回时候不会更新逻辑栈,但没有关系,因为只有中转页才会用到逻辑栈
  7. 逻辑栈更新机制
    1. 跳转、返回中转页时更新
    2. navigateTo时更新
    3. redirectTo时更新
    4. reLaunch时更新
    5. navigateBack时更新
    6. switchBar 时置空,因为原生栈会把之前的清空,只保留当前tab的路由栈

步骤图示

  1. 用户操作
  2. 小程序历史栈
  3. js逻辑栈:自行维护的js路由栈
  4. “中”表示中转页
  5. “1 2 3 4 5 6 7 8 9 A B C”表示不同的页面路径 | 用户操作 | 小程序历史栈 | js逻辑栈 | 后续操作 | | —- | —- | —- | —- | | 1 2 3 4 5 6 7 8 | 1 2 3 4 5 6 7 8 | 1 2 3 4 5 6 7 8 | 跳转页面9 | | 1 2 3 4 5 6 7 8 9 | 1 2 3 4 5 6 7 8 9 | 1 2 3 4 5 6 7 8 9 | 跳转页面A | | 1 2 3 4 5 6 7 8 9 A | 1 2 3 4 5 6 7 8 中 A | 1 2 3 4 5 6 7 8 9 A | 跳转页面B | | 1 2 3 4 5 6 7 8 9 A B | 1 2 3 4 5 6 7 8 中 B | 1 2 3 4 5 6 7 8 9 A B | 跳转页面C | | 1 2 3 4 5 6 7 8 9 A B C | 1 2 3 4 5 6 7 8 中 C | 1 2 3 4 5 6 7 8 9 A B C | 返回 | | 1 2 3 4 5 6 7 8 9 A B | 1 2 3 4 5 6 7 8 中 B | 1 2 3 4 5 6 7 8 9 A B | 返回 | | 1 2 3 4 5 6 7 8 9 A | 1 2 3 4 5 6 7 8 中 A | 1 2 3 4 5 6 7 8 9 A | 返回 | | 1 2 3 4 5 6 7 8 9 | 1 2 3 4 5 6 7 8 9 | 1 2 3 4 5 6 7 8 9 | 返回(逻辑栈不更新) | | 1 2 3 4 5 6 7 8 | 1 2 3 4 5 6 7 8 | 1 2 3 4 5 6 7 8 9 | 返回(逻辑栈不更新) | | 1 2 3 4 5 6 7 | 1 2 3 4 5 6 7 | 1 2 3 4 5 6 7 8 9 | 返回(逻辑栈不更新) | | 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 7 8 9 | 返回(逻辑栈不更新) | | 1 2 3 4 5 | 1 2 3 4 5 | 1 2 3 4 5 6 7 8 9 | 跳转页面6 | | 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 | 跳转页面7 | | 1 2 3 4 5 6 7 | 1 2 3 4 5 6 7 | 1 2 3 4 5 6 7 | … |


源码

未完待续c x

使用方式