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

相关推荐
weixin_382395234 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__5 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.5 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~6 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华7 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子9 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅9 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni10 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学11 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端