
连续打开六个详情页再一路返回。有人会以为把Navigation的stackSizeLimit设成 3第四次入栈时最早的页面就从“返回历史”里消失了。API 26 的实际定义不是这样限制的是活跃页面节点数量较早页面节点会按先入先出被销毁但对应的NavPathInfo仍在路由栈中后续可以重新创建页面。这个区别会直接影响两件事返回键还能不能回到早期页面以及那个页面里临时选中的筛选项、滚动位置该放哪里。只盯NavPathStack.size()很容易把“页面重建”误判成“路由丢失”。API 26 到底限制了什么华为的 Navigation API 参考在 2026 年 9 月 9 日更新了configuration(config: NavigationConfiguration)。其中stackSizeLimit从 API 26.0.0 开始提供默认值 0小于等于 0 表示不限制大于 0 时活跃页面节点超过上限会按先入先出销毁更早入栈的节点但其NavPathInfo保留允许之后重建。该接口只用于 Stage 模型。用法并不复杂难的是理解它没有替你保存页面组件里的每一份临时状态Entry ComponentV2 struct NavigationRoot { private stack: NavPathStack new NavPathStack(); build() { Navigation(this.stack) { Button(打开详情).onClick(() { this.stack.pushPath({ name: detail, param: { id: 42 } }); }); } .navDestination(this.pageBuilder) .configuration({ stackSizeLimit: 3 }); // API 26.0.0 } Builder pageBuilder(name: string, param: Object) { if (name detail) { NavDestination() { Text(详情 ${JSON.stringify(param)}); } .title(详情); } } }以上是接口位置示意。detail页在真实工程中还需要按项目路由组织、类型约束和 SDK 编译结果调整不要把这段当成已经在设备上跑过的完整工程。更重要的是stackSizeLimit: 3不等于“只允许三个历史路由”也不保证一定节省某个固定数值的内存是否改善内存应当用 Profiler 实测。案例一六次入栈后为什么还能返回第二页复现步骤创建一个Navigation将限制设为 3依次推入详情 1 到详情 6给每个页面的aboutToAppear、销毁回调和NavPathStack变更打上同一组序号。进入第六页后向前返回观察第二页是否重新创建。按文档定义逻辑上有两层数据。路由信息可以保留 1 到 6活跃节点上限为 3较早的节点会被回收。返回早期路由时系统依据保留的路由信息重新创建页面。配图是这两层的关系示意不是系统内部对象数量截图。观察项预期问题应记录的证据路由信息早期NavPathInfo是否仍可返回入栈顺序、返回顺序、路由参数页面实例早期NavDestination是否重建创建/销毁回调次数和页面标识页面数据筛选、滚动等是否还在重建前后的字段值及其保存位置内存限额是否真的改善占用相同路线、相同设备上的 Profiler 对比我先用一段可运行的小模型验证“历史路由”和“活跃实例”不能混为一谈。它不是 ArkUI 的替身只用于检查业务代码有没有把两个概念写成同一个数组export function projectNavigation(routes, stackSizeLimit) { if (!Number.isInteger(stackSizeLimit)) throw new TypeError(limit must be an integer); const keep stackSizeLimit 0 ? routes.length : stackSizeLimit; return { retainedRouteInfo: [...routes], activePageNames: routes.slice(-keep).map(route route.name), evictedPageNames: routes.slice(0, Math.max(0, routes.length - keep)).map(route route.name), }; }六条路由、限制 3 的本地测试得到retainedRouteInfo.length 6activePageNames为page4/page5/page6更早的page1/page2/page3进入待重建组。真实系统的创建时序和内存变化仍需 API 26 设备验证不能拿这个数组模型当性能实测。案例二返回第二页筛选条件为什么变回默认值如果页面把filter未读和滚动位置只放在页面组件的临时状态里早期节点被销毁并重建后组件会重新初始化。文档明确保证保留的是NavPathInfo并没有说每个组件字段都自动复原。因此需要把“回去后还必须保持”的数据明确放进路由参数、共享状态或持久化层不同数据按寿命分层别全塞进路由参数。一个可控的做法是路由参数保存稳定业务 ID 和初始条件短时的筛选/滚动快照存到按“页面名 业务 ID”索引的状态表。返回重建时先读快照没有快照才退回路由初始值export function restorePageInput(route, snapshots) { const key ${route.name}:${route.param.id}; return { id: route.param.id, filter: snapshots.get(key)?.filter ?? route.param.initialFilter ?? all, scrollIndex: snapshots.get(key)?.scrollIndex ?? 0, }; }这个快照表若只存在进程内就只解决同一次运行中的页面重建进程被杀后仍要恢复时应使用项目已有的持久化方案。还要在业务对象删除、退出该流程或数据版本变化时清掉旧快照否则会把上次的筛选条件错误套给另一个对象。我验证了什么哪些还需要设备验收上述两段模型代码在本地用 Node.js 跑了三项测试六条历史路由与三个活跃节点分离按业务 ID 恢复筛选与滚动快照限制为 0 或负数时按“不限制”处理。结果3 pass / 0 fail。这是模型测试不是 HarmonyOS SDK 编译结果也不是 Profiler 的内存收益证明。设备验收建议固定同一套六层路径分别用默认配置和stackSizeLimit: 3测试记录页面创建/销毁回调、返回后的参数和局部状态再对比 Profiler 快照。若页面重建成本很高限制太小可能以更多重建换取较少活跃节点选 2、3 还是 5应该由这组数据决定不宜照搬示例值。我会把它当成一个“内存与重建成本”的取舍开关而不是普通的返回栈截断器。先确认页面参数可重建再确保关键状态有明确归属最后才调上限。这样返回历史、页面实例和业务状态各负其责。参考Navigation API 参考 · Navigation 跳转指导 · 自定义组件生命周期