想象一下,你经营着一家开在手机里的“小程序餐厅”。餐厅本身是小程序,App 生命周期是餐厅的开业与打烊流程;每一张餐桌是一个“页面 Page”,一桌客人从入座、点菜到结账离开的全程,就是页面生命周期;而客人在大厅、包间、吧台之间走动的路线,就是页面路由。作为老板,你要决定何时开门备货、何时迎宾、客人换桌时怎么引导、后厨怎么传菜、食材怎么保鲜。这篇文章就用“管餐厅”的视角,带你把小程序生命周期与页面路由一次看透。
小程序生命周期与页面路由是移动端开发的地基工程。掌握它,你就能精准掌控资源释放时机、设计合理的页面跳转闭环,写出不掉帧、不泄漏、体验顺滑的小程序。
目录
可视化演示
演示小程序App/Page/Component生命周期回调与页面栈路由跳转机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
生命周期 App Page onLoad→onUnload 生命周期回调管理资源
应用生命周期:餐厅的开门与打烊
一家餐厅每天的开业节奏是固定的:开门前采购备料,门一开迎客,忙完一轮暂时歇口气,客人走了再重新迎接。小程序 App 的生命周期也是如此——它就是整个餐厅的营业时间表。onLaunch 是开门前的备料环节,小程序冷启动时只触发一次;onShow 是正式开门迎客,每次从后台回到前台都会触发;onHide 是挂上“暂停营业”的牌子;onError 则是后厨着火时的应急机制。
从技术角度讲,App 级生命周期回调在小程序的 app.js 中定义,是整个应用的“总开关”。onLaunch 适合做初始化工作,比如检查登录状态、拉取全局配置;onShow 适合恢复需要实时更新的数据;onHide 适合暂停正在播放的音频、关闭高频定位。它们的触发时机由微信/支付宝/抖音等平台统一调度,开发者只需在对应回调里填入合适的“工作清单”。
用一个时间轴可以更清楚地看出规律:应用从启动开始,经历“前台-后台-前台”的循环,直到用户退出小程序。注意 onShow 和 onHide 是成对出现的,而 onLaunch 一生只会出现一次。这个规律决定了全局资源的加载与释放时机。
开一家店,老板必须知道什么时候备料、什么时候开门、什么时候打烊。小程序全局的状态管理也是这样:把初始化放进 onLaunch,把恢复动作放进 onShow,把暂停动作放进 onHide,这台餐厅永远不会在错误的时间做错误的事。
onShow 再次响起迎客铃。- 首次前台时刻
t_show^(1)表示应用第一次出现在用户面前的时刻,对应onShow首次触发。 - 退入后台时刻
t_hide^(1)是应用被切到后台的时刻,Δ_back是后台停留时长,onHide在此刻触发。 - 再次前台时刻
t_show^(2)是用户重新回到小程序的时刻,整个循环等于“首屏使用时长 + 后台停留时长”。
页面生命周期:一桌客人的用餐全程
餐厅的每张餐桌都有自己独立的“接待流程”:客人进门被引导入座,服务员递上菜单,后厨开始备菜,客人用完餐结账离开,服务员撤桌清扫。小程序里每个页面 Page 的生命周期,就是这张餐桌的完整服务流程。当 onLoad 触发时,相当于客人刚入座,服务员递上点菜单;onShow 是客人真正看到这桌的状态;onReady 是菜品和餐具全部就位;onHide 是客人暂时离席;onUnload 则是客人结账走人、撤桌清洁。
在代码层面,页面生命周期回调是每个 Page 的标配。首次进入页面时回调顺序固定为 onLoad → onShow → onReady。其中 onLoad 只执行一次,且能接收上一个页面通过路由带来的参数;onShow 每次页面变得可见都会触发;onReady 表示首帧渲染完成,可以安全操作组件。当页面被 navigateTo 压入后台时触发 onHide,被 navigateBack 或 redirectTo 移除时触发 onUnload。
理解这套顺序的价值在于掌握“资源分配”的时机。onLoad 适合拉取数据、初始化变量;onReady 适合获取节点信息、开始动画;onUnload 必须清理该页面专属的定时器和监听器,否则相当于客人走了,桌上的餐具和垃圾没人收拾,越积越多。
客人走后不撤桌,下一桌客人就没法入座。同理,页面被卸载时不清除定时器、不解绑监听,内存就会持续膨胀。把 onUnload 当成“撤桌流程”,每次必做清理,你的小程序就能长时间流畅运行。
- 初次拜访路径
onLoad负责接收参数并初始化,onShow让页面可见,onReady完成渲染。三者次序固定,不可颠倒。 - 再次访问路径页面已在栈中时,重新显示只走
onShow,隐藏只走onHide,不会再触发onLoad。
组件生命周期:餐具的流转
好的餐厅离不开餐具的高效流转。刀叉、盘子、杯子从仓库取出、摆上桌、被使用、最后撤下清洗,构成一个完整的循环。小程序的自定义组件 Component 也有类似的生命周期:created 相当于餐具从仓库取出(此时组件实例已创建但还没上桌);attached 相当于餐具被摆到餐桌上(组件挂载进页面节点树);ready 是餐具各就各位、可以正式使用;detached 是撤桌清洗(组件从节点树移除)。
技术细节上,组件生命周期建议写在 lifetimes 字段中。created 时组件还没有进入到页面结构里,所以不能调用 this.triggerEvent 之类依赖组件关系的接口,但可以初始化自身数据;attached 之后可以获取组件上下文;ready 之后可以安全操作组件内部的节点。除此之外还有 observers 字段用于监听属性变化——就像服务员时刻留意客人的水杯,一旦空了就主动加水。
组件生命周期与页面生命周期的关系是“嵌套”的:页面 onLoad 时内部的组件可能正在走 created → attached,页面 onReady 时组件的 ready 也通常已结束。开发者在小程序工具中打开生命周期跟踪面板,可以直观看到这种“先父后子、子先就绪”的触发层次。
餐具流转不清洗会滋生细菌,组件销毁不清理会泄漏内存。把 detached 当作“撤桌清洗”的固定流程,组件就能在页面任何角落安全反复地使用。
- 创建环节
created表示组件实例刚被构造,适合初始化内部数据,但此时组件还未进入页面节点树。 - 挂载环节
attached表示组件已挂载到页面树中,可以访问组件外部传入的属性与插槽内容。 - 就绪环节
ready表示组件渲染完成,可安全操作组件内节点,对应“餐具各就各位”。 - 移除环节
detached表示组件从节点树移除,必须在此清理组件内的监听器和定时器。
路由跳转方式:客人的四种移动动线
客人在餐厅里的移动方式不止一种:从大厅走到包间,服务员会记住他的来路方便带他回来;从包间直接换到另一间包间,原包间立即被回收;吃完原路返回;或者通过固定通道去吧台取饮料。小程序页面路由的四种 API 恰好对应这四种动线。navigateTo 是“走进包间”,新页面压入页面栈,当前页保留在栈中并隐藏;redirectTo 是“换桌”,当前页被替换出栈并卸载;navigateBack 是“原路返回”,弹出栈顶页面;switchTab 是“走通道去吧台”,只能跳转到 tabBar 页面且不能携带参数。
代码层面,这些 API 都是全局方法:wx.navigateTo、wx.redirectTo、wx.navigateBack、wx.switchTab,以及“清场重来”的 wx.reLaunch。用栈的视角看,navigateTo 就是 push,navigateBack 就是 pop,redirectTo 是“弹出栈顶再压入新页”,switchTab 则特殊地清空非 tabBar 页面。选择哪种方式取决于业务语义:需要返回上一页就用 navigateTo,完成操作后不希望用户回到旧页面就用 redirectTo。
一个常见的业务场景是登录流程:用户从首页进入登录页,登录成功后应该用 redirectTo 跳回首页或业务页,而不是 navigateTo,否则用户按返回键又会回到登录页,就像换桌后服务员还带客人回已经撤掉的旧桌。
动线设计决定客人体验。支付成功后用 redirectTo 防止回退到收银台,详情页跳转用 navigateTo 确保用户可以逐级返回。路由 API 选对了,用户在小程序里的每一步都走得顺理成章。
- 入栈操作
navigateTo将新页面P_new追加到页面栈末尾,原栈保持不变,当前页被隐藏。 - 替换操作
redirectTo先从栈中移除栈顶页面P_top,再将新页面压入,实现“换桌不回头”。
页面栈管理:服务员的动线账本
服务员手里有一本动线账本,每次带客人去新包间就记一笔,客人离开就划掉一笔,账本的深度有限。小程序正是用“页面栈”来管理所有页面的。页面栈是一个后进先出的结构:navigateTo 入栈,navigateBack 出栈,redirectTo 替换栈顶。平台对栈深度有硬性限制——最多 10 层,超过后会跳转失败,就像账本最多只能记 10 条动线,写满了就不能再带客人去新包间。
开发者可以通过 getCurrentPages() 获取当前页面栈的数组,最后一个元素就是当前页面实例。利用这个 API 可以做两件很实用的事:一是拿到上一页实例并调用它的方法更新数据,二是打印当前栈结构排查路由异常。页面栈的进出规则决定了 onShow 与 onUnload 的触发顺序——入栈时新页面 onLoad 后 onShow,旧页面 onHide;出栈时栈顶页面 onUnload,新栈顶页面 onShow。
栈深度限制是新手最容易踩的坑。如果页面反复用 navigateTo 跳转而不及时 navigateBack,到第 11 次跳转就会失败。所以在设计“详情页 → 评论页 → 举报页”这类深层链路时,务必评估某些中间页是否应用 redirectTo 替换掉,主动控制账本厚度。
动线账本记得太多,服务员会手忙脚乱。小程序同样如此——定期用 getCurrentPages() 检查栈深度,用 redirectTo 代替无意义的 navigateTo 链路,你的页面导航就不会“爆栈”。
- 统计栈深对页面栈
Stack中的每个页面累加计数,得到当前栈深度。 - 深度上限平台规定栈深不超过 10,
Depth(Stack) ≤ 10是合法状态,超过则跳转失败。
参数传递机制:点菜单上的需求条
客人想吃什么,写在点菜单上递给后厨;客人有什么忌口,记录在餐厅的熟客档案里;服务员之间需要实时沟通,直接通过对讲机喊话。小程序页面之间的数据传递同样有三种主要通道。第一种是 query 参数:跳转时把数据拼在 URL 后面,目标页在 onLoad(options) 中接收,就像点菜单上写明“少辣、不要香菜”。第二种是全局数据 app.globalData:挂载在 App 实例上的公共对象,适合存放登录令牌、用户信息,相当于餐厅的公用档案。第三种是本地缓存 wx.setStorageSync:把数据持久化到设备存储中,适合存放草稿、历史记录,相当于熟客档案柜。
实战中 parameter 传递的细节容易被忽略:navigateTo 的 URL 长度有限且需要编码特殊字符,对象类型必须先 JSON.stringify 再传;switchTab 不能带参数,此时应借助全局变量或缓存;EventChannel 可以在两个页面间建立双通道通信,类似给服务员配备对讲机,navigateTo 成功回调里通过 eventChannel.emit 传输数据,目标页在 onLoad 里 getOpenerEventChannel().on 监听接收。
选择哪种通道没有绝对标准,核心是数据和生命周期要匹配:临时一次性数据走 query,会话级数据走 globalData,需要跨冷启动保留的数据走缓存,父子页面间的即时回传走 EventChannel。
传参方式没有银弹,只有最合适的场景。把一次性需求写在“点菜单”上,把长期信息放进“档案柜”,把临时协作丢给“对讲机”,你的页面间数据流就会像餐厅后厨一样井然有序。
- 页面参数解码
query参数在 URL 中编码传输,目标页拿到后通过Decode还原成原始数据。 - 全局数据读取
app.globalData[key]直接从全局对象中按键取值,不受页面栈变化的干扰。
缓存与内存:食材保鲜与库存管理
再大的餐厅也有冰柜容量上限;再稳的小程序也有存储限制。本地缓存就像餐厅的冰柜——里面可以存熟客口味、半成品食材等,但冰柜总共只有 10MB 空间,超过上限后写入失败。缓存 API 分为同步与异步两套:wx.setStorageSync / wx.getStorageSync 是“吧台即时存取”,读写快但会阻塞 JS 线程;wx.setStorage / wx.getStorage 是“后仓批量存取”,不阻塞主线程,适合大体积数据。除了总量上限,还要注意缓存数据在用户清理微信缓存时会丢失,所以不能把它当作永久数据库。
与缓存同等重要的是内存管理。页面的 onUnload 必须清理定时器和监听器,否则“撤桌不洗碗”会引发内存泄漏;onHide 时应该暂停视频和音频播放,减少后台占用;图片资源尽量走 CDN 懒加载,避免一次加载过多大图。组件销毁时同样要清理 observers 之外的动态监听。内存清理的黄金法则是:谁创建,谁释放。
实际开发中,缓存策略和生命周期的配合非常关键:在 onLoad 中先读缓存展示旧数据,再发请求更新数据并写回缓存——这是“缓存优先、网络兜底”的经典模式;在 onUnload 中把用户编辑的草稿写入缓存,防止误退出丢数据。这样既保证了首屏速度,又照顾了数据新鲜度。
把缓存当成冰柜、把内存当成后厨空间,定期“清库存”是经验丰富的老板的必修课。定时器清掉、监听器解绑、大图懒加载、缓存限量使用,这套组合拳打下来,小程序就能像高效运转的餐厅一样长期不卡顿。
- 存储总量约束
Storage中所有键k的大小之和,不能超过 10MB 的平台额定配额。 - 存活对象统计
Mem_live表示堆内存中仍被引用的对象总量,引用链越长越难释放,小程序越卡。
AI 应用场景
页面停留时长埋点分析
阶段:数据采集与处理
解决的问题:传统做法是手动在各页面 onShow、onHide 里写重复的统计代码,代码冗余且容易漏掉页面。利用生命周期钩子统一封装埋点 SDK,可在 onShow 记录进入时间、onHide 计算停留时长,为 AI 用户画像模型提供高质量行为数据。
具体案例:在电商小程序的 Page.onShow 中调用埋点 SDK 上报 page_start,在 onHide 上报 page_end 并附带时长。后端清洗后喂给推荐模型,用于预测用户下一单可能进入的商品页。
路由拦截与登录态校验
阶段:模型推理与业务集成
解决的问题:未登录用户直接访问订单页会触发接口 401,体验很差。AI 助手型的业务页更需要确保用户处于有效会话。通过在页面 onLoad 中统一读取 globalData.token,无令牌则 redirectTo 到登录页,登录成功再 navigateBack,形成闭环。
具体案例:某 AI 绘画小程序中,用户点击“我的作品”时页面 onLoad 检查本地缓存的登录态,未登录则跳转授权页,同时携带 redirect_url 参数,登录后自动回到原页面并带着用户 token 刷新作品列表。
本地缓存驱动的 AI 会话草稿
阶段:应用开发与部署
解决的问题:AI 对话页面中,用户编辑的提示词(prompt)如果不缓存,切出小程序后就会丢失。利用 onHide 自动将草稿写入 wx.setStorageSync,在 onLoad 恢复,实现会话的“无感续聊”。
具体案例:AI 写作助手的提问页,用户在页面中输入长文本 prompt,中途切到微信聊天再回来时,onShow 立即从缓存恢复草稿内容;用户输入完成后点击生成,AI 请求发出后若页面被回收,onUnload 也会兜底保存,确保内容不丢。
Python 演示
class Page: def __init__(self, name): self.name = name def on_load(self, params): print("[Page:%s] onLoad, params=%s" % (self.name, params)) def on_show(self): print("[Page:%s] onShow" % self.name) def on_ready(self): print("[Page:%s] onReady" % self.name) def on_hide(self): print("[Page:%s] onHide" % self.name) def on_unload(self): print("[Page:%s] onUnload" % self.name) class MiniApp: MAX_DEPTH = 10 def __init__(self): self.stack = [] self.global_data = {} def launch(self): print("[App] onLaunch") self.show() def show(self): print("[App] onShow") def hide(self): print("[App] onHide") def navigate_to(self, page, params=None): if len(self.stack) >= self.MAX_DEPTH: raise RuntimeError("page stack is full") if self.stack: self.stack[-1].on_hide() self.stack.append(page) page.on_load(params or {}) page.on_show() page.on_ready() def redirect_to(self, page, params=None): self.stack.pop().on_unload() self.stack.append(page) page.on_load(params or {}) page.on_show() page.on_ready() def back(self, delta=1): for _ in range(delta): self.stack.pop().on_unload() if self.stack: self.stack[-1].on_show() if __name__ == "__main__": app = MiniApp() app.launch() home = Page("home") app.navigate_to(home) detail = Page("detail") app.navigate_to(detail, {"id": 1001}) app.back() edit = Page("edit") app.redirect_to(edit)
class Page:定义页面模型,每个页面拥有 onLoad、onShow、onReady、onHide、onUnload 五个生命周期方法,对应正文中的“餐桌服务流程”。def on_load(self, params):模拟页面接收路由参数,对应实际小程序中onLoad(options)接收 query 参数。self.stack = []用列表模拟页面栈,栈顶永远是列表末尾元素,对应“服务员的动线账本”。if len(self.stack) >= self.MAX_DEPTH:校验栈深度是否超过 10 层,超过则抛出异常,对应平台的栈深限制。self.stack[-1].on_hide()压入新页面前,先将当前栈顶页面隐藏,符合navigateTo的时序。self.stack.append(page)新页面入栈,相当于服务员在账本上新记一条动线。self.stack.pop().on_unload()弹出栈顶页面并触发其 onUnload,对应navigateBack的撤桌流程。def back(self, delta=1):按指定步数出栈,出栈后让新栈顶页面触发 onShow,对应“原路返回”。
常见误区
误区我从列表页点进详情页,编辑完返回再点另一篇详情,详情页的 onLoad 应该每次都执行吧?不然数据怎么刷新的?
正解onLoad 只在页面实例首次创建时执行一次,相当于客人第一次入座才递菜单。当页面通过 navigateBack 从栈中恢复时,触发的是 onShow 而不是 onLoad。要在每次进入都刷新数据,应该把拉取逻辑放在 onShow 中,因为它每次可见都会触发。这和“熟客再访只需打招呼,不用重新点菜”是同一个道理。
为何常见:新手往往把“页面每次出现”和“页面重新创建”混为一谈,以为回到页面就等于重新加载,忽略了页面栈的复用机制。
误区小程序页面随便跳,反正导航栏有返回按钮,用户总能原路返回。
正解页面栈深度上限是 10 层,超出后 navigateTo 直接失败。这就像服务员的动线账本最多记 10 页,写满就不能再带客人去新包间了。电商“首页→搜索结果→商品详情→店铺→…”这类深层链路很容易触顶,需要及时用 redirectTo 替换中间页,或用 navigateBack 回退。
为何常见:很多开发者只关注“跳转能不能成功”,却不关注“返回链路有没有闭环”,等到线上出现跳转静默失败才排查出栈深问题。
误区我把数据存到 `wx.setStorageSync` 里,这不就是本地数据库吗?用户随时都能读出来。
正解缓存像冰柜,虽然能保鲜,但冰柜容量只有 10MB,且用户主动“清理微信存储”时缓存会被清空,小程序版本升级也可能导致部分缓存失效。缓存应放可重建的半成品数据(如草稿、用户设置),绝不可放唯一重要的数据。付费记录、账号凭证等核心信息应存服务端,本地只做加速。
为何常见:开发者习惯把缓存当作数据库使用,混淆了“临时存储”与“持久化存储”的边界,直到用户清缓存后数据全丢才意识到问题。
误区我在 onUnload 里清了定时器,所以页面资源肯定能释放。
正解onUnload 在正常 navigateBack 出栈时确实会触发,但小程序在某些极端场景(如内存告警被系统直接回收)下不会走正常的 onUnload 流程。因此重要的清理逻辑不能只在 onUnload 做,还要在 onHide 里做好兜底——前台的定时器暂停、视频停止播放等操作应双保险。这就像餐厅不仅要靠跑单结算,还要在打烊前定期盘点后厨。
为何常见:开发者把 onUnload 当作万能清理钩子,忽略了移动端系统“强杀进程”的现实——系统可不会等你优雅地洗完碗再断电。
面试题
Q1. 小程序应用级生命周期中,只在冷启动时触发一次的回调是哪个?
- A.onShow
- B.onLaunch← 正确答案
- C.onHide
- D.onError
答案:B。onLaunch 对应餐厅开门前的备料,整个营业日只做一次;onShow 每次回前台都触发;onHide 每次进后台触发;onError 在出错时触发。备料只做一次,迎客每次都要。
Q2. 页面首次加载时,生命周期回调的正确顺序是?
- A.onShow → onLoad → onReady
- B.onLoad → onShow → onReady← 正确答案
- C.onLoad → onReady → onShow
- D.onReady → onShow → onLoad
答案:B。初始顺序为 onLoad → onShow → onReady,对应“入座 → 看到餐桌 → 服务就绪”。其他选项顺序颠倒,违反了页面初始化的固定时序。
Q3. 使用 wx.navigateTo 从首页跳转到列表页后,首页的生命周期状态是?
- A.触发 onUnload,从页面栈移除
- B.触发 onHide,保留在页面栈中← 正确答案
- C.触发 onShow,继续在前台运行
- D.不触发任何回调,原样保留
答案:B。navigateTo 是“走进包间”,原页面像客人暂时离开旧桌一样触发 onHide,但桌子还留着(页面栈保留),返回时直接 onShow 恢复。A 是 redirectTo 的表现;C 错误,新页面在前台;D 错误,隐藏必触发 onHide。
Q4. 小程序页面栈的最大深度是多少层?
- A.5 层
- B.10 层← 正确答案
- C.15 层
- D.20 层
答案:B。平台规定页面栈最多 10 层,超过 10 层后 navigateTo 会失败。这就像动线账本最多记录 10 条动线,写满后拒绝再带客人去新包间,必须先返回再跳转。
Q5. 下列哪些操作会导致当前页面触发 onUnload?
- A.调用 wx.redirectTo 替换当前页← 正确答案
- B.调用 wx.navigateBack 返回上一页← 正确答案
- C.调用 wx.navigateTo 跳转新页面
- D.调用 wx.switchTab 切换 tab
答案:AB。redirectTo 将当前页弹出栈并卸载,navigateBack 将栈顶弹出并卸载,二者都会触发 onUnload。navigateTo 只是隐藏当前页,switchTab 会关闭非 tabBar 页面但保留 tabBar 页面本身,若当前页是 tabBar 页则不卸载。
Q6. 在页面 anyPage 中调用 wx.navigateBack({ delta: 2 }),下列说法正确的是?
- A.一定会返回到栈中倒数第三个页面
- B.若栈深为 2,则 back 失败且无任何回调
- C.出栈的两个页面都会触发 onUnload← 正确答案
- D.新栈顶页面会触发 onReady
答案:C。navigateBack 弹出 delta 个页面,每个被弹出的页面触发 onUnload;若 delta 超过栈深则回退到栈底页。B 错在“无任何回调”——返回后会触发新栈顶 onShow;A 超界时不一定到达倒数第三页;D 错,新栈顶触发的是 onShow 而非 onReady。
Q7. 关于自定义组件生命周期,下列说法正确的是?
- A.created 阶段可以调用 triggerEvent 触发事件
- B.attached 阶段组件已挂载到页面节点树← 正确答案
- C.detached 阶段组件仍可正常操作节点
- D.ready 阶段组件尚未渲染完成
答案:B。attached 表示组件已挂载到节点树,可以访问外部属性与插槽,相当于餐具已经摆上桌。created 时组件未挂载,不能触发事件;detached 时组件已被移除,不能操作;ready 时渲染已完成,D 说法相反。
Q8. 要在页面 B 中接收页面 A 通过 wx.navigateTo 传递的参数,应该在哪个回调中读取?
- A.onShow(options)
- B.onLoad(options)← 正确答案
- C.onReady(options)
- D.onHide(options)
答案:B。onLoad 的生命周期回调会收到路由参数 options,对应“客人入座时服务员递上写好的点菜单”。onShow 和 onReady 不接收参数,onHide 在页面隐藏时触发故无法收到新参数。
Q9. 下列哪些做法可以有效降低小程序的内存压力?
- A.在 onUnload 中清除页面定时器← 正确答案
- B.在 onHide 中暂停视频播放← 正确答案
- C.将大对象长期挂在 globalData 上
- D.图片使用 CDN 懒加载← 正确答案
答案:ABD。清除定时器、暂停视频、图片懒加载分别对应“撤桌洗碗、离店关灯、按需进货”,都能降低常驻内存。而将大对象长期挂在 globalData 上等于把不用的食材一直霸占冰柜,阻碍内存回收,属于反面做法。
Q10. 关于 wx.switchTab,下列描述正确的有?
- A.只能跳转到 tabBar 页面← 正确答案
- B.会关闭所有非 tabBar 页面← 正确答案
- C.会销毁所有 tabBar 页面实例
- D.跳转时不能携带 query 参数← 正确答案
答案:ABD。switchTab 是“走固定通道去吧台”,只能去 tabBar 页面,同时关闭其他非 tabBar 页面,并且无法携带参数。tabBar 页面实例会保留而非销毁,所以 C 错误。设计 tabBar 切换时要把共享数据放缓存或全局变量,而不是依赖 URL 传参。