微信小程序路由详细探索
以下内容均为开发文档的内容,我只是摘抄记录我所认为更有帮助的内容,并着重标记一些关键名词!
路由的时机
路由会以事件形式表示,由微信客户端下发给小程序基础库,下发后客户端和基础库将分别同时处理这一次路由事件。路由事件的发起可以大致分为以下两类:
通过用户的操作(如按下返回按钮)发起。通过这种方式发起时,路由事件将直接由客户端下发到基础库执行;由开发者通过 API(如 wx.navigateTo)或者组件(如 )发起。通过这种方式发起时,基础库将首先向客户端发起路由请求,客户端确认路由可以被执行后,再将路由事件下发到基础库。其中,如果路由被确定执行,API 的 success 回调函数或组件的 success 事件将被触发,否则将触发 fail。
当一次路由被确定执行(API 或组件通知 success)时,没有操作可以取消这一次路由。
当多次路由被连续发起时,如果当前的路由事件还未处理完毕,后续的路由事件将等待当前路由处理,并排队依次执行,直到所有待处理的路由都被执行完毕。
一个简单的例子:用户点击返回按钮触发了 navigateBack,小程序在页面栈当前栈顶页的 onUnload 中调用 wx.redirectTo,并不能 将当前正在被销毁的页面重定向为一个新页面,而是会先完成页面返回,再将页面返回后的新栈顶页重定向到新的页面。
路由类型
小程序目前的路由类型可以大致分为以下七种:
1. 小程序启动
openType: appLaunch
小程序启动路由 appLaunch 表示一个新的小程序启动,并加载第一个页面。appLaunch 在每个小程序实例中会且仅会出现一次,且每个小程序实例启动时的第一个路由事件必定为 appLaunch。
触发方式:
appLaunch 仅能由小程序冷启动被动触发,不能由开发者主动触发,启动后也不能通过其他用户操作触发。页面栈及生命周期处理:
由于 appLaunch 必定是启动时的第一个路由,而路由前没有任何页面存在,此时页面栈必定为空。appLaunch 会创建路由事件指定的页面,并将其推入页面栈作为栈中唯一的页面。在这个过程中,这个页面的 onLoad, onShow 两个生命周期将依次被触发。
2. 打开新页面
openType: navigateTo
打开新页面路由 navigateTo 表示打开一个新的页面,并将其推入页面栈。
触发方式
调用 API wx.navigateTo, Router.navigateTo使用组件 用户点击一个视频小窗(如 video)
navigateTo 的目标必须为非 tabBar 页面。
页面栈及生命周期处理
navigateTo 事件发生时,页面栈当前的栈顶页面将首先被隐藏,触发 onHide 生命周期;之后框架将创建路由事件指定的页面,并将其推入页面栈作为新的栈顶。在这个过程中,这个新页面的 onLoad, onShow 两个生命周期将依次被触发。
作为一种特殊情况,如果 navigateTo 事件发生时,页面栈当前的栈顶页面满足小窗模式逻辑,或事件由用户点击视频小窗发起,那么页面栈及生命周期的的处理会有所不同。
3. 页面重定向
openType: redirectTo
页面重定向路由 redirectTo 表示将页面栈当前的栈顶页面替换为一个新的页面。
触发方式
调用 API wx.redirectTo, Router.redirectTo
使用组件
redirectTo 的目标必须为非 tabBar 页面。页面栈及生命周期处理
redirectTo 事件发生时,页面栈当前的栈顶页面将首先被弹出并销毁,在此过程中,这个栈顶页面的 onUnload 生命周期将被触发;之后框架将创建路由事件指定的页面,并将其推入页面栈作为新的栈顶。在这个过程中,这个新页面的 onLoad, onShow 两个生命周期将依次被触发。
4. 页面返回
openType: navigateBack
页面返回路由 navigateBack 表示将页面栈当前的栈顶的若干个页面依次弹出并销毁。
触发方式
调用 API wx.navigateBack, Router.navigateBack使用组件
如果页面栈中当前只有一个页面,navigateBack 调用请求将失败(无论指定的 delta 是多少);
如果页面栈中当前的页面数量少于调用时指定的 delta + 1(即调用后页面数量将少于一个),navigateBack 将弹出到只剩页面栈当前的页面栈底的页面为止(即至少保留一个页面)。
页面栈及生命周期处理
navigateBack 事件发生时,页面栈当前的栈顶页面将被弹出并销毁,并触发这个页面的 onUnload 生命周期;以上操作将被重复执行多次,直到弹出的页面数量等于指定的页面数量,或当前页面栈中只剩下一个页面。之后,页面栈新的栈顶页面的 onShow 生命周期将被触发。
一种特殊情况是,如果 navigateBack 发生时,页面栈当前的栈顶页面满足小窗模式逻辑,或事件由用户点击视频小窗发起,那么页面栈及生命周期的的处理会有所不同。
5. Tab 切换
openType: switchTab
Tab 切换路由 wx.switchTab 表示切换到指定的 tab 页面。
触发方式
调用 API wx.switchTab, Router.switchTab使用组件 用户点击 Tab Bar 中的 Tab 按钮
switchTab 的目标必须为 tabBar 页面。
页面栈及生命周期处理
由于 navigateTo 和 redirectTo 不能指定 tabBar 页面作为目标,因此当一个 tabBar 页面出现在页面栈中时,它必定为页面栈的第一个页面(即栈底页面);同时,框架会保证任一 tabBar 页面在小程序中最多同时存在一个页面实例。switchTab 的行为主要基于这两点进行。
switchTab 事件发生时,如果当前页面栈中存在多于一个页面,页面栈当前的栈顶页面将被弹出并销毁,并触发这个页面的 onUnload 生命周期;以上操作将被重复执行多次,直到页面栈中只剩下一个页面。之后,根据页面栈中仅剩的页面进行不同的处理:
如果这个页面即为目标 tabBar 页面:
如果路由事件开始时页面栈中存在多于一个页面(即目标 tabBar 页面不是栈顶页面),触发目标 tabBar 页面的 onShow 生命周期;否则(路由事件开始时目标 tabBar 页面是栈顶页面),不触发任何生命周期,直接结束;
否则(该页面不为目标 tabBar 页面时):
将这个页面从页面栈中弹出;
如果这个页面为其他 tabBar 页面,该页面成为悬垂页面,并:
如果路由事件开始时页面栈中只有一个页面(即该 tabBar 页面是栈顶页面),触发它的 onHide 生命周期;否则(路由事件开始时该 tabBar 页面不是栈顶页面),不触发它的任何生命周期;
否则(这个页面为非 tabBar 页面时),销毁该页面,触发 onUnload 生命周期;
如果目标 tabBar 页之前已经被创建过(现在是一个悬垂页面),将其推入页面栈,触发 onShow 生命周期;否则(目标 tabBar 页不存在实例),创建目标 tabBar 页并推入页面栈,依次触发 onLoad, onShow 生命周期。
6. 重加载
openType: reLaunch, autoReLaunch
重加载路由 reLaunch 或 autoReLaunch 表示销毁当前所有的页面,并载入一个新页面。
重加载路由的两种 openType 的区别主要为是否由开发者主动触发(或是由用户触发),这两种 openType 的路由逻辑基本一致。
触发方式
(reLaunch)调用 API wx.reLaunch, Router.reLaunch(reLaunch)使用组件 (autoReLaunch)小程序处于后台时,用户从扫码或分享等场景重新进入小程序
reLaunch 可以指定任意页面作为目标页面,无论它是否是小程序的首页或是否 tabBar 页。
请注意:reLaunch 及 autoReLaunch 仅代表一种路由,并不等于小程序重启,小程序会在当前的 AppService 上继续运行,既不会重新启动 AppService 的 JavaScript 运行环境,也不会重新注入小程序代码或触发 App.onLaunch 生命周期,各种 JS 的全局变量或全局状态也不会被重置。
页面栈及生命周期处理
reLaunch 或 autoReLaunch 事件发生时,页面栈中的所有页面将由顶至底依次被弹出并销毁,触发 onUnload 生命周期;之后所有悬垂页面将以不确定的顺序逐个被销毁,触发 onUnload 生命周期。所有页面都被销毁后,目标页面将被创建,并推入页面栈成为栈中唯一的页面,依次触发 onLoad 和 onShow 两个生命周期。
7. 关闭小窗页面
openType: dismissPip
关闭小窗页面路由 dismissPip 表示关闭一个正处于小窗模式的页面。