【HarmonyOS NEXT】Navigation路由导航

一、背景

在鸿蒙开发中,提供了两种路由导航方式,分别是Router和Navigation,之前的文章介绍过Router的使用,此篇文章主要总结下Navigation的使用及与Router对比区别

二、Navigation简介

2.1、简介

Navigation是路由导航的根视图容器,一般作为页面(@Entry)的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。一次开发,多端部署场景下,Navigation组件能够自动适配窗口显示大小,在窗口较大的场景下自动切换分栏展示效果。

2.2、关键属性与方法

属性 类型 描述
title ResourceStr | CustomBuilder 页面标题。支持字符串、资源引用或自定义构建器。
titleMode NavigationTitleMode 标题栏显示模式(如 FullMiniFree)。
hideTitleBar boolean 是否隐藏标题栏。
hideToolBar boolean 是否隐藏工具栏。
menus Array<NavigationMenuItem> | CustomBuilder 设置页面右上角菜单。
toolbarConfiguration Array<ToolbarItem> | CustomBuilder 设置工具栏内容(替代已废弃的 toolBar)。
hideBackButton boolean 是否隐藏返回键(对 NavDestination 的返回图标无效)。
mode NavigationMode 导航栏显示模式,如支持单栏(Stack)、分栏(Split)和自适应(Auto) 默认值:NavigationMode.Auto 自适应:基于组件宽度自适应单栏和双栏。
navDestination (name: string, param: unknown) => void 重要:用于创建 NavDestination 组件的构建器函数。

三、Navigation基本用法

有两种使用方法,分别为动态构建和静态配置

3.1、动态构建

TypeScript 复制代码
@Entry
@Component
struct Index {
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()

  aboutToAppear() {
    // 压入初始页面
    this.pageInfos.pushPathByName("home", "");
  }

  @Builder
  routerMap(name: string) {
    if (name === "home") {
      Home()
    } else if (name === "mine") {
      Mine();
    }
  }

  build() {
    Navigation(this.pageInfos) {
    }
    .hideNavBar(true)
    .navDestination(this.routerMap)
  }
}

@Component
struct Home {
  // 使用@Consume装饰器获取页面栈
  @Consume('pageInfos') pageInfos: NavPathStack;

  build() {
    NavDestination() {
      Button('Home页面')
        .onClick(()=>{
          this.pageInfos.pushPathByName('mine','')
        })
    }.title('Home')

  }
}

@Component
struct Mine {
  // 使用@Consume装饰器获取页面栈
  @Consume('pageInfos') pageInfos: NavPathStack;

  build() {
    NavDestination() {
      Text('Mine页面')
    }.title('Mine')
    .onBackPressed(() => {
      const popDestinationInfo = this.pageInfos.pop(); // 弹出路由栈栈顶元素
      console.info('pop' + '返回值' + JSON.stringify(popDestinationInfo));
      return true;
    })
  }
}

3.2、静态配置

路由导航主要元素:

1、导航页Navigation和子页NavDestination

2、路由表RouterMap

3、路由栈NavPathStack

3.2.1、构建导航栏

TypeScript 复制代码
@Entry
@Component
struct Index {
  pageStack : NavPathStack = new NavPathStack();

  build() {
    Navigation(this.pageStack){
    }.onAppear(() => {
      this.pageStack.pushPathByName("PageOne", null, false);  //添加路由操作
    })
    .hideNavBar(true)
  }
}

3.2.2、构建子页

TypeScript 复制代码
// 跳转页面入口函数
@Builder
export function PageOneBuilder() {
  PageOne();
}

@Component
struct PageOne {
  pathStack: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Button('跳转')
    }
    .title('PageOne')
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}

3.2.3、创建路由表

1、在跳转目标模块的配置文件module.json5添加路由表配置:

TypeScript 复制代码
  {
    "module" : {
      "routerMap": "$profile:route_map"  //添加路由表配置数据
    }
  }

2、添加完路由配置文件地址后,需要在工程resources/base/profile中创建route_map.json文件。添加如下配置信息:

TypeScript 复制代码
{
  "routerMap": [
    {
      "name": "PageOne",
      "pageSourceFile": "src/main/ets/view/PageOne.ets",
      "buildFunction": "PageOneBuilder",
      "data": {
        "description": "this is PageOne"
      }
    },
    {
      "name": "PageTwo",
      "pageSourceFile": "src/main/ets/view/PageTwo.ets",
      "buildFunction": "PageTwoBuilder",
      "data": {
        "description": "this is PageTwo"
      }
    }
  ]
}

配置说明如下:

配置项 说明
name 可自定义的跳转页面名称。
pageSourceFile 跳转目标页在包内的路径,相对src目录的相对路径。
buildFunction 跳转目标页的入口函数名称,必须以@Builder修饰。
data 应用自定义字段。可以通过配置项读取接口getConfigInRouteMap获取。

3.2.4、路由操作

TypeScript 复制代码
@Entry
@Component
struct Index {
  pageStack : NavPathStack = new NavPathStack();

  build() {
    Navigation(this.pageStack){
    }.onAppear(() => {
      this.pageStack.pushPathByName("PageOne", null, false);  //添加路由操作
    })
    .hideNavBar(true)
  }
}
TypeScript 复制代码
// 跳转页面入口函数
@Builder
export function PageOneBuilder() {
  PageOne();
}

@Component
struct PageOne {
  pathStack: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Button('跳转')
        .onClick(()=>{
          this.pathStack.pushPathByName('PageTwo','')  //路由操作
        })
    }
    .title('PageOne')
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}

3.3、两种方法主要区别对比

特性 动态构建 静态配置
配置方式 代码内@Builder函数 外部JSON配置文件
类型检查 运行时检查 编译时强类型检查
热更新 支持 不支持,需要重新打包
维护性 代码路由耦合 配置与代码分离
适用场景 简单应用、快速原型 大型应用、团队协作

四、Navigation生命周期

Navigation作为路由容器,其生命周期承载在NavDestination组件上,以组件事件的形式开放。

  1. 根页面(@Entry修饰的页面)生命周期
  • 遵从标准页面生命周期,关键事件包括:
    • aboutToAppear:页面即将显示时触发。
    • onPageShow:页面显示后触发(注意:不推荐在Navigation根页面使用)。
    • aboutToDisappear:页面即将隐藏时触发。
  1. NavDestination子页面生命周期
  • 通过组件事件监听:
    • onAppear:通用生命周期事件,子页面显示时触发。
    • onShown:子页面布局完全显示后触发。
    • onActive:子页面处于激活态时触发(如从后台回到前台)。
    • onInactive:子页面失去激活态时触发(如应用退到后台)。
生命周期事件 触发时机说明
aboutToAppear 自定义组件生命周期 :在创建自定义组件后,执行其 build() 函数之前调用。
onWillAppear NavDestination 独有NavDestination 创建后,挂载到组件树之前执行。
onAppear 通用组件生命周期NavDestination 组件挂载到组件树时执行。
onWillShow NavDestination 独有 :组件布局显示之前执行,此时页面不可见
onShown NavDestination 独有:组件布局显示之后执行,此时页面已完成布局。
onActive NavDestination 独有:页面处于激活态(处于栈顶且可操作)时触发。
onWillHide NavDestination 独有:组件触发隐藏之前执行(应用切换到后台不会触发)。
onInactive NavDestination 独有:页面变为非激活态(如被遮挡或非栈顶)时触发。
onHidden NavDestination 独有:组件触发隐藏后执行(如新页面入栈、当前页出栈或应用切后台)。
onWillDisappear NavDestination 独有:组件即将销毁之前执行,有转场动画则在动画前触发。
onDisappear 通用组件生命周期NavDestination 组件从组件树上卸载时执行。
aboutToDisappear 自定义组件生命周期:自定义组件析构销毁之前执行。

五、Navigation 与 Router 的对比

业务场景 / 能力 Navigation Router
官方推荐与演进 是未来主推方向,持续演进新功能 后续不再新增功能
一多能力 支持,自适应不同设备与屏幕 不支持
路由栈管理 支持 ,可获取并操作 NavPathStack 不支持,只能获取基本状态信息
参数传递方式 引用传递,性能更优 深拷贝,性能开销相对较大
路由数量限制 无限制 最多32个页面
传参获取 支持获取指定页面的参数 不支持获取指定页面参数
沉浸式页面 原生支持 需通过 Window 配置实现
模态嵌套路由 支持在模态框、弹窗中嵌套 不支持
共享元素动画 支持 不支持
路由拦截 支持 不支持
页面结构 页面是组件,由 NavDestination 包裹 页面是 @Entry 修饰的独立组件
适用场景 同一模块内的页面跳转,复杂UI结构 跨模块的页面跳转

使用建议:

  • 优先使用 Navigation:特别是新启动的项目,或者在同一个模块内进行页面跳转时。它提供了更强大的功能和更好的性能。

  • Router 的适用场景 :当需要进行跨模块的页面跳转时(例如主模块跳转到动态共享包中的页面),目前仍需使用 Router。

相关推荐
坚果的博客2 小时前
Cordova 开发鸿蒙应用完全指南
华为·harmonyos
爱笑的眼睛115 小时前
HarmonyOS应用开发中HTTP网络请求的封装与拦截器深度实践
华为·harmonyos
爱笑的眼睛116 小时前
HarmonyOS截屏与录屏API深度解析:从系统权限到像素流处理
华为·harmonyos
zhangfeng11337 小时前
医疗智能体(eiHealth) 3.4.0 使用指南(for 华为云Stack 8.5.0) 0. 华为除了这个 还有医疗 和生信方面的 产品
华为·华为云·生物信息
Android疑难杂症8 小时前
鸿蒙Notification Kit通知服务开发快速指南
android·前端·harmonyos
BlackWolfSky9 小时前
鸿蒙三方库httpclient使用
华为·harmonyos·鸿蒙
爱笑的眼睛1110 小时前
HarmonyOS 分布式输入法开发指南:实现跨设备无缝输入体验
华为·harmonyos
夏文强10 小时前
HarmonyOS开发-系统AI视觉能力-图片识别
人工智能·华为·harmonyos
Random_index10 小时前
#HarmonyOS篇:管理组件拥有的状态
华为·harmonyos