核心概念: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%的路由状态管理问题。

相关推荐
IT_陈寒2 分钟前
Java性能优化:10个让你的Spring Boot应用提速300%的隐藏技巧
前端·人工智能·后端
whysqwhw20 分钟前
Hippy 跨平台框架扩展原生自定义组件的完整实现方案对比
前端
dasseinzumtode35 分钟前
nestJS 使用ExcelJS 实现数据的excel导出功能
前端·后端·node.js
子兮曰38 分钟前
🔥C盘告急!WSL磁盘暴增?三招秒清20GB+空间
前端·windows·docker
Jinuss39 分钟前
Vue3源码reactivity响应式篇之EffectScope
前端·vue3
stoneship42 分钟前
网页截图API-Npm工具包分享
前端
Jedi Hongbin1 小时前
Three.js shader内置矩阵注入
前端·javascript·three.js
etcix1 小时前
dmenux.c: integrate dmenu project as one file
c语言·前端·算法
光影少年1 小时前
react16到react19更新及底层实现是什么以及区别
前端·react.js·前端框架
超人不会飛1 小时前
vue3 markdown组件|大模型应用专用
前端·vue.js·人工智能