核心概念:Navigation路由生命周期是什么

🧩 一、核心概念:Navigation路由生命周期是什么?

在Navigation路由体系里,每个页面(NavDestination)从"出生"到"消失",会经历一系列自动触发的函数,我们称为生命周期。它们像闹钟一样,在特定节点提醒你该做什么操作,比如加载数据、清理资源等。和传统Router不同,NavDestination不走 onPageShow/onPageHide,而是用自己专属的生命周期7。


⏳ 二、完整生命周期流程(时序与用途)

想象一个页面从打开到关闭的全过程:

sequenceDiagram 新页面->>当前页面: 新页面aboutToAppear组件创建,可初始化变量 新页面->>当前页面: 新页面onWillAppear即将显示,可改路由栈 新页面->>当前页面: 新页面onAppear已挂载显示 新页面->>当前页面: 新页面onShown完全展示,适合开启动画 当前页面-->>新页面: 当前页面onWillHide即将隐藏 当前页面-->>新页面: 当前页面onHidden完全隐藏 当前页面-->>新页面: 当前页面onWillDisappear即将销毁 当前页面-->>新页面: 当前页面onDisappear已销毁 新页面-)当前页面: 当前页面aboutToDisappear最终清理资源

关键阶段解析

  • aboutToAppear:页面"出生证",在这里初始化数据 🎯
  • onReady :唯一能拿到 NavPathStack 路由栈对象的地方,用于后续跳转6
  • onShown:页面完全可见,适合开启动画或自动播放
  • onHidden:用户离开页面,暂停视频或计时器 ⏸️
  • aboutToDisappear:最后清理内存,注销监听事件 🧹

⚙️ 三、基础配置:路由表与页面注册

1. 路由表配置(route_map.json)

json

ruby 复制代码
// src/main/resources/base/profile/route_map.json
{
  "routerMap": [
    {
      "name": "detailPage",       // 路由名称
      "pageSourceFile": "pages/DetailPage.ets", // 文件路径
      "buildFunction": "DetailBuilder" // 页面构建函数
    }
  ]
}

2. Module注册(module.json5)

json

kotlin 复制代码
{
  "module": {
    "routerMap": "$profile:route_map" // 指向路由表
  }
}

3. 页面代码示例

typescript

scss 复制代码
// DetailPage.ets
@Builder
export function DetailBuilder() { // 和路由表里的buildFunction一致
  DetailComponent()
}

@Component
struct DetailComponent {
  build() {
    NavDestination() {
      // 页面内容...
    }
    .onReady((ctx: NavDestinationContext) => {
      const stack = ctx.pathStack; // 获取路由栈
      stack.pushPath({ name: "nextPage" }); // 后续跳转
    })
    .onShown(() => {
      console.log("页面已完全展示");
    })
  }
}

🚀 四、生命周期在典型场景中的应用

场景1:列表页进入详情页时暂停视频

typescript

scss 复制代码
// 列表页
@Component
struct ListPage {
  @State videoPlaying: boolean = true;
  
  build() {
    NavDestination() {
      VideoPlayer().play($rawfile('video.mp4'))
    }
    .onHidden(() => {
      this.videoPlaying = false; // 离开时暂停
    })
    .onShown(() => {
      if (!this.videoPlaying) {
        this.videoPlaying = true; // 返回时恢复播放
      }
    })
  }
}

场景2:从不同页面返回时差异化刷新

typescript

ini 复制代码
// 目标页:检查来源决定是否刷新
aboutToAppear() {
  const routes = stack.getAllPathName();
  const lastPage = routes[routes.length - 2]; // 上一个页面名
  if (lastPage === "SettingsPage") { // 从设置页返回需刷新
    this.refreshData();
  }
}

场景3:避免重复创建资源(单例模式)

typescript

scss 复制代码
let dataCache: DataType | null = null; // 全局缓存

@Component
struct DataPage {
  aboutToAppear() {
    if (!dataCache) {
      dataCache = loadHeavyData(); // 只加载一次
    }
  }
  aboutToDisappear() {
    // 不清理缓存,下次复用
  }
}

⚠️ 五、避坑指南:常见问题解决

  1. 生命周期不触发?

    • 检查是否用 @Builder 函数包裹了组件(必须项)2
    • 确认API版本≥12(旧版有兼容问题)2
  2. 路由跳转后页面卡顿?

    • aboutToDisappear 释放资源(如关闭数据库连接)
    • 避免在 onReady 执行耗时操作❌
  3. 根页面不触发 onPageShow

    • Navigation容器本身不是页面,用 onShown 代替 onPageShow7

🔍 六、对比:Navigation vs Router 的生命周期

能力 Navigation (NavDestination) Router (@Entry页面)
初始化 aboutToAppear aboutToAppear
页面显示 onShown onPageShow
页面隐藏 onHidden onPageHide
获取路由栈 ✅ 通过onReadyctx.pathStack ❌ 仅能获取当前页
跨设备状态同步 ✅ 通过分布式API ⚠️ 需手动实现

🧪 七、动手练习:完整示例

typescript

scss 复制代码
// 主页:带跳转按钮
@Entry
@Component
struct HomePage {
  private stack: NavPathStack = new NavPathStack();
  
  build() {
    Navigation(this.stack) {
      Button("跳转到详情页")
        .onClick(() => {
          this.stack.pushPath({ name: "detailPage" });
        })
    }
  }
}

// 详情页:记录生命周期
@Builder
export function DetailBuilder() {
  DetailComponent()
}

@Component
struct DetailComponent {
  @State eventLog: string = "";
  
  build() {
    NavDestination() {
      Text(this.eventLog).fontSize(16)
    }
    .onAppear(() => { this.eventLog += "可见\n"; })
    .onShown(() => { this.eventLog += "完全展示\n"; })
    .onHidden(() => { this.eventLog += "隐藏\n"; })
    .aboutToDisappear(() => { 
      showToast("页面即将关闭");
    })
  }
}

💎 最后总结

Navigation的生命周期是基于组件 而非页面,核心在于 onReady(拿路由栈)、onShown/onHidden(代替传统显示/隐藏)、aboutToDisappear(资源清理)。用好这几个节点,就能解决90%的路由状态管理问题。

相关推荐
傅里叶3 分钟前
Flutter在OrangePi 5 Plus上视频播放锁死问题
前端·flutter
古夕36 分钟前
my-first-ai-web_问题记录03——NextJS 项目框架基础扫盲
前端·javascript·react.js
曲意已决1 小时前
《深入源码理解webpac构建流程》
前端·javascript
去伪存真1 小时前
前端如何让一套构建产物,可以部署多个环境?
前端
KubeSphere1 小时前
EdgeWize v3.1.1 边缘 AI 网关功能深度解析:打造企业级边缘智能新体验
前端
掘金安东尼2 小时前
解读 hidden=until-found 属性
前端·javascript·面试
1024小神2 小时前
jsPDF 不同屏幕尺寸 生成的pdf不一致,怎么解决
前端·javascript
滕本尊2 小时前
构建可扩展的 DSL 驱动前端框架:从 CRUD 到领域模型的跃迁
前端·全栈
借月2 小时前
高德地图绘制工具全解析:线路、矩形、圆形、多边形绘制与编辑指南 🗺️✏️
前端·vue.js
li理2 小时前
NavPathStack 是鸿蒙 Navigation 路由的核心控制器
前端