HarmonyOS开发:路由容器Navigation的使用详解

news2025/7/9 5:41:14

​目录

  • 前言
  • 路由容器Navigation
  • Navigation组成
  • 路由跳转操作
  • Navigation下的页面生命周期
  • 最后

前言

众所周知,HarmonyOS作为华为推出的新一代操作系统,其开发框架提供了全新的能力和组件,以支持跨平台应用开发,越来越多的开发者加入到鸿蒙应用开发中,而在HarmonyOS的应用开发中,HarmonyOS提供了一套全新的开发框架和API,路由容器Navigation扮演着至关重要的角色,它负责页面的跳转和导航控制,是应用组件化开发中不可或缺的一部分。那么这篇文章,就来详细介绍路由容器Navigation的使用方法,并通过具体的示例源码,帮助大家深入了解和学习使用。

路由容器Navigation

先来回顾一下Navigation概念,其实在HarmonyOS开发中,Navigation是ArkUI中中一个用于管理页面路由的容器组件,它允许开发者定义应用中的页面路径,并实现页面之间的跳转,它一般作为首页的根容器,适用于模块内和跨模块的路由切换,最重要的是它支持一次开发,多端部署场景。Navigation的设计理念与Web开发中的路由机制相似,但专为HarmonyOS的架构和性能要求定制,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果,是鸿蒙官方推荐的导航组件(相比于Router,Navigation的支持面更广,所以建议大家选择Navigation)。

Navigation的组成

Navigation组件主要包含​导航页(NavBar)和子页(NavDestination),其中导航页由标题栏(Titlebar,包含菜单栏menu)、内容区(Navigation子组件)和工具栏(Toolbar)组成,而且导航页可以通过hideNavBar属性进行隐藏,导航页不存在页面栈中,导航页和子页,以及子页之间可以通过路由操作进行切换。在不同尺寸的设备上,Navigation组件能够自适应显示大小,自动切换分栏展示效果,可以用于根控制器实现页面的跳转和传值,同时可以实现系统或自定义标题栏、导航Item等。简答概括,如下所示。

Navigation组件主要包含​导航页(NavBar)、子页(NavDestination)两部分组成。其中,导航页包含以下三个部分:

  • 标题栏(Titlebar,包括菜单栏menu):通过title属性来设置标题;
  • 内容区(Navigation子组件):默认首页显示导航内容或非首页显示,二者通过路由进行切换;
  • 工具栏(Toolbar):通过toolbarConfiguration实现对工具栏的配置。

另外就是Navigation组件通过mode属性设置页面的显示模式,Navigation组件显示模式分为三种:单页面模式、自适应模式和分栏模式。

1、单页面模式

先来分享一下单页面模式页面示意图,具体如下所示:
在这里插入图片描述
根据上图的单页面模式布局示意图,左边为导航页,右边为子页,可以通过路由转换实现页面来回的切换跳转。根据上面的流程图,这里着重分享Navigation组件在单页面模式的三个知识点:标题栏、菜单栏、工具栏。

(1)标题栏

标题栏在界面顶部,用于呈现界面名称和操作入口,Navigation组件通过titleMode属性设置标题栏模式,标题栏模式分为Mini模式和Full模式。

Mini模式:普通型标题栏,用于一级页面不需要突出标题的场景。

Navigation() {
  // 详细代码
  ...
}
.titleMode(NavigationTitleMode.Mini)

Full模式:强调型标题栏,用于一级页面需要突出标题的场景。

Navigation() {
  // 详细代码
  ...
}
.titleMode(NavigationTitleMode.Full)

(2)菜单栏

菜单栏位于Navigation组件的右上角,开发者可以通过menus属性进行设置,其中menus支持Array和CustomBuilder两种参数类型。在使用Array类型时,竖屏最多支持显示3个图标,横屏最多支持显示5个图标,多余的图标会被放入自动生成的更多图标。

let TooTmp1: NavigationMenuItem = {'value': "", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
let TooTmp2: NavigationMenuItem = {'value': "", 'icon': "./image/ic_public_search.svg", 'action': ()=> {}}
let TooTmp3: NavigationMenuItem = {'value': "", 'icon': "./image/ic_public_add.svg", 'action': ()=> {}}

Navigation() {
  // 详细代码
  ...
}
.menus([
  TooTmp1,
  TooTmp2,
  TooTmp3
 ])

(3)工具栏

工具栏位于Navigation组件的底部,作为开发者,我们可以通过toolbarConfiguration属性进行设置,需要注意的是该属性需要传入一个Toolbarltem构成的数组。

let TooTmp1: ToolbarItem = {'value': "func", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
let TooTmp2: ToolbarItem = {'value': "func", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
let TooTmp3: ToolbarItem = {'value': "func", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
let TooBar: ToolbarItem[] = [TooTmp1,TooTmp2,TooTmp3]
Navigation() {
  // 详细代码
  ...
}
.toolbarConfiguration(TooBar)

2、自适应模式

关于自适应模式,其实Navigation组件默认为自适应模式,这时候的mode属性为NavigationMode.Auto。在自适应模式下,当页面宽度大于等于一定阈值的时候,Navigation组件采用分栏模式,反之采用单栏模式。

Navigation() {
  // 详细代码
  ...
}
.mode(NavigationMode.Auto)

3、分栏模式

先来看一下分栏模式示意图,具体如下所示:
在这里插入图片描述
关于分栏模式,其实就是将mode属性设置为NavigationMode.Split,Navigation组件即可设置为分栏显示模式。

Navigation() {
  // 详细代码
  ...
}
.mode(NavigationMode.Split)

路由跳转操作

不用多讲想必大家也清楚,路由跳转是Navigation的核心功能之一,在HarmonyOS开发中,实现页面跳转的大概步骤如下所示:

  1. 定义路由:在应用的配置文件中定义页面的路由信息。
  2. 创建导航器实例:在需要进行页面跳转的地方创建导航器实例。
  3. 执行路由跳转:使用导航器的navigate方法执行页面跳转。

其实Navigation路由相关的操作都是基于页面栈NavPathStack提供的方法进行,每个Navigation都需要创建并传入一个NavPathStack对象,用于管理页面,其中主要涉及页面跳转、页面返回、页面替换、页面删除、参数获取、路由拦截等功能。(根据鸿蒙官方文档可知,从API version 12开始,页面栈允许被继承,我们可以在派生类中自定义属性和方法,也可以重写父类的方法。派生类对象可以替代基类NavPathStack对象使用。)简单的示例代码如下所示:

@Entry
@Component
struct Index {
  // 创建一个页面栈对象并传入Navigation
  pageStack: NavPathStack = new NavPathStack()

  build() {
    Navigation(this.pageStack) {
    }
    .title('MyPage')
  }
}

1、跳转操作

关于跳转操作,其实是NavPathStack通过Push相关的接口去实现页面跳转的功能,主要分为三类:普通跳转、带返回回调的跳转、带错误码的跳转。

(1)普通跳转,主要是通过页面的name去跳转,并可以携带param。

this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" })
this.pageStack.pushPathByName("PageOne", "PageOne Param")

(2)带返回回调的跳转,跳转时添加onPop回调,能在页面出栈时获取返回信息,并进行处理。

this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => {
    console.log('Pop page name is: ' + popInfo.data.name + ', result: ' + JSON.stringify(popInfo.result))
});

(3)带错误码的跳转,跳转结束会触发异步回调,返回错误码信息,简单的示例代码如下所示:

this.pageStack.pushDestinationByName('PageOne', "PageOne Param")
.catch((error: BusinessError) => {
    console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
}).then(() => {
    console.error('Push destination succeed.');
});

2、返回操作

关于返回操作,其实是NavPathStack通过Pop相关接口去实现页面返回功能,简单的示例代码如下所示:

// 返回到上一页
this.pageStack.pop()

// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne")

// 返回到索引为1的页面
this.pageStack.popToIndex(1)

// 返回到根首页(清除栈中所有页面)
this.pageStack.clear()

3、替换操作

关于替换操作,NavPathStack通过Replace相关接口去实现页面替换功能,简单的示例代码如下所示:

// 将栈顶页面替换为PageOne
this.pageStack.replacePath({ name: "PageOne", param: "PageOne Param" })
this.pageStack.replacePathByName("PageOne", "PageOne Param")

4、删除操作

关于删除操作,其实是NavPathStack通过Remove相关接口去实现删除页面栈中特定页面的功能,简单的示例代码如下所示:

// 删除栈中name为PageOne的所有页面
this.pageStack.removeByName("PageOne")

// 删除指定索引的页面
this.pageStack.removeByIndexes([1,3,5])

5、获取参数操作

关于参数获取操作,是NavPathStack通过Get相关接口去获取页面的一些参数,简单的示例代码如下所示:

// 获取栈中所有页面name集合
this.pageStack.getAllPathName()

// 获取索引为1的页面参数
this.pageStack.getParamByIndex(1)

// 获取PageOne页面的参数
this.pageStack.getParamByName("PageOne")

// 获取PageOne页面的索引集合
this.pageStack.getIndexByName("PageOne")

6、路由拦截操作

关于路由拦截操作,NavPathStack提供了setInterception方法,用于设置Navigation页面跳转拦截回调,需要注意的是该方法需要传入一个NavigationInterception对象,其中该对象包含三个回调函数,具体如下所示:
在这里插入图片描述
**需要注意:**上面的三个回调函数,无论是哪个回调,在进入回调的时候页面栈都已经发生了变化。

作为鸿蒙开发者,我们可以在willShow回调中通过修改路由栈来实现路由拦截重定向的能力,简单的示例代码如下所示:

this.pageStack.setInterception({
  willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
    operation: NavigationOperation, animated: boolean) => {
    if (typeof to === "string") {
      console.log("target page is navigation home page.");
      return;
    }
    // 将跳转到PageTwo的路由重定向到PageOne
    let target: NavDestinationContext = to as NavDestinationContext;
    if (target.pathInfo.name === 'PageTwo') {
      target.pathStack.pop();
      target.pathStack.pushPathByName('PageOne', null);
    }
  }
})

Navigation下的页面生命周期

接下来再来分享一下Navigation下的页面生命周期,Navigation作为路由容器,其生命周期承载在NavDestination组件上,以组件事件的形式开放,在Navigation的控制下,页面的生命周期管理也有所不同。根据鸿蒙官方的释义,Navigation下的页面生命周期大致可分为三类:自定义组件生命周期、通用组件生命周期和自有生命周期(需要说明的是,aboutToAppear和aboutToDisappear是自定义组件的生命周期。如果NavDestination外层包含自定义组件时则存在;OnAppear和OnDisappear是组件的通用生命周期,剩下的六个生命周期为NavDestination独有)。

其中,我们需要根据页面的生命周期状态来管理页面资源,优化应用性能,具体详细的页面生命周期如下图所示:
在这里插入图片描述

  • aboutToAppear:在创建自定义组件后,执行其build()函数之前执行(也就是NavDestination创建之前),允许在该方法中改变状态变量,更改将在后续执行build()函数中生效。
  • onWillAppear:NavDestination创建后,挂载到组件树之前执行,在该方法中更改状态变量会在当前帧显示生效。
  • onAppear:通用生命周期事件,NavDestination组件挂载到组件树时执行。
    onWillShow:NavDestination组件布局显示之前执行,此时页面不可见(应用切换到前台不会触发)。
  • onShown:NavDestination组件布局显示之后执行,此时页面已完成布局。
  • onWillHide:NavDestination组件触发隐藏之前执行(应用切换到后台不会触发)。
  • onHidden:NavDestination组件触发隐藏后执行(非栈顶页面push进栈,栈顶页面pop出栈或应用切换到后台)。
  • onWillDisappear:NavDestination组件即将销毁之前执行,如果有转场动画,会在动画前触发(栈顶页面pop出栈)。
  • onDisappear:通用生命周期事件,NavDestination组件从组件树上卸载销毁时执行。
  • aboutToDisappear:自定义组件析构销毁之前执行,不允许在该方法中改变状态变量。

这里分享一个简单的示例代码,具体如下所示:

@Component
export struct LoginPageView{
@Consume('pageInfo') pageStack : NavPathStack;
    aboutToAppear(): void {...}
    build() {
        NavDestination(){...}.hideTitleBar(true)
            .onReady(()=>{})
            .onAppear(()=>{...})
            .onShown(()=>{...})
            .onHidden(()=>{...})
            .onDisAppear(()=>{...})
     }
    aboutToDisappear(): void {...}
}

最后还是要啰嗦一句,鸿蒙官方强力推荐开发者使用Navigation,原先使用Router的应用建议尽快切换成Navigation,避免由于页面的持续增加导致迁移工作量变大,所以说我们在实际鸿蒙开发中首选Navigation路由容器。

最后

通过本文的详细介绍,我们可以看到HarmonyOS中的Navigation是一个功能丰富且灵活的路由管理组件,详细介绍了HarmonyOS中路由容器Navigation的使用方法,包括导航器的创建和路由的操作、页面跳转的执行,不仅简化了页面跳转的实现,还提供了对页面生命周期的精细控制。所以说掌握Navigation的使用对于HarmonyOS应用开发者来说至关重要,通过具体的示例源码,我们可以看到Navigation在HarmonyOS应用开发中的实际应用。随着HarmonyOS生态的不断发展,我们可以看到Navigation将会发挥越来越重要的作用,尤其是在实际开发过程中的具体应用。作为开发者,我们应当深入理解并熟练运用Navigation,以构建更加流畅和高效的用户体验。让我们共同期待HarmonyOS带来的无限可能,最后也希望这篇文章能帮助开发者更好地理解和使用HarmonyOS的Navigation相关的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

红黑树实现详解

实践意义 在各方面,红黑树要比AVL树性能更好,用途也更广泛 map&set底层都主要靠红黑树 概念 性质 插入时,抽象图 cur为新插入 插入时颜色更新逻辑图 板书

bugku-web-never_give_up

解题思路 F12查看请求和响应&#xff0c;查找线索 相关工具 base64解码URL解码Burp Suit抓包 页面源码提示 <!--1p.html--> 2. 去访问这个文件&#xff0c;发现直接跳转到BUGKU首页&#xff0c;有猫腻那就下载看看这个文件内容吧 爬虫下载这个文件 import requests …

20240804 每日AI必读资讯

25亿独角兽CEO带头跑路&#xff0c;携30员工卖身谷歌&#xff01;AI大佬&#xff1a;AGI泡沫几周就要破 - CEO一并带走的&#xff0c;还有Character.AI负责模型训练和语音AI的员工&#xff0c;也就是130名员工中的30人。他们将加入谷歌&#xff0c;参与Gemini AI项目。 - Cha…

【C++学习第19天】二分图

一、如何判断一个图是二分图&#xff1f; 二、代码 1、判断是否为二分图 #include <iostream> #include <algorithm> #include <cstring>using namespace std;const int N 200010;int n, m; int h[N], e[N], ne[N], idx; int color[N];void add(int a, in…

JavaScript 继承百花齐放:从原型链到 ES6 类

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 在 JavaScript 中&#xff0c;继承是一个重要的知识点&#xff0c;上篇文章中我们已…

【Java】Java Swing 图书管借阅管理系统(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

python rsa如何安装

Python中的一些模块是用一个包管理器来发布的&#xff0c;RSA模块就是&#xff0c;所以首先需要安装setup tools工具。 1、下载文件&#xff1a;ez_setup.py 2、安装&#xff1a; sudo python ez_setup.py 3、下载RSA安装包&#xff1a;rsa-3.1.1-py2.7.egg 4、安装RSA&…

牛客JS题(二十一)数组扁平化

注释很详细&#xff0c;直接上代码 涉及知识点&#xff1a; 递归flat字符串操作正则表达式替换 题干&#xff1a; 我的答案 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /></head><body><script&…

Dubbo源码深度解析(中)

接着《Dubbo源码深度解析(上)》继续讲&#xff0c;上篇博客主要讲Dubbo提供的三个注解的作用&#xff0c;即&#xff1a;EnableDubbo、DubboComponentScan、EnableDubboConfig。其中后两个注解是在EnableDubbo上的&#xff0c;因此在启动类上加上EnableDubbo注解&#xff0c;等…

数据分析模型:洞察数据背后的奥秘

数据分析模型&#xff1a;洞察数据背后的奥秘 事件分析模型通过对用户行为事件的深入剖析&#xff0c;能够了解用户在产品上的具体行为&#xff0c;为产品优化和营销策略提供了有力依据。漏斗分析模型则专注于用户转化流程&#xff0c;帮助找出业务流程中的薄弱环节&#xff0c…

[Meachines] [Easy] Sense PFSense防火墙RCE

信息收集 IP AddressOpening Ports10.10.10.60TCP:80,443 $ nmap -p- 10.10.10.60 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 80/tcp open http lighttpd 1.4.35 |_http-title: Did not follow redirect to https://10.10.10.60/ |_http-server-header…

zlm-openRtpServer使用

http://127.0.0.1/index/api/openRtpServer?port50253&tcp_mode1&stream_idtest123&secretLSAjqhPDsC0IcL27hI6U8heTxgnTlZlW使用getRtpInfo查看这个流的情况&#xff0c;注意只有这个端口在接受流的时候&#xff0c;才会返回数据 http://127.0.0.1/index/api/ge…

【文献阅读】TAM: Topology-Aware Margin Loss for Class-Imbalanced Node Classification

Abstract 在类别不平衡的图数据中学习无偏的节点表示是一项具有挑战性的任务&#xff0c;因为相邻节点之间存在相互作用。现有研究的共同点在于&#xff0c;它们根据少数类节点的总体数量“作为一个整体”进行补偿&#xff08;忽略了图中的节点连接&#xff09;&#xff0c;这…

理解<共轭复数乘法,复数乘法,复数除法>

目录 复数乘法共轭复数乘法的理解复数除法 复数乘法 共轭复数乘法的理解 共轭复数乘法&#xff1a;可以理解为滤波&#xff0c;计算两序列的相关。即一个序列固定&#xff0c;另一个序列进行滑动计算该点的累积和。因为傅里叶变换的卷积定理&#xff0c;时域卷积对于频域相乘。…

web漏洞-知识点详解

先放张图&#xff01;右边漏洞比左边漏洞更重要&#xff01;右边漏洞更多&#xff01;重点讲述右边漏洞&#xff01; sql注入 危害情况&#xff1a;可以获取网站数据库中的数据&#xff0c;如果数据中有敏感信息&#xff0c;比如管理员账号密码&#xff0c;就可以登录后台 漏…

学生管理系统之更新和删除、筛选

学生管理系统之更新和删除 建立新的窗口 添加组件 进行布局 使用Widget把二个放在一块,作为一列,然后全选进行栅格布局,最后添加弹簧进行微调。 编写增加的槽函数 在主函数中调用对话框

CC++内存魔术:掌控无形资源

hello,uu们,今天呢我们来详细讲解C&C的内存管理,好啦,废话不多讲,开干 1:C/C内存分布 2:C语言中动态内存管理方式:malloc/calloc/realloc/free 3:C内存管理方式 3.1:new/delete操作内置类型 3.1.1:代码1 3.1.2:代码2 3.2:new和delete操作自定义类型 3.2.1:C语言创建…

初识增强现实(AR)

初识增强现实&#xff08;AR&#xff09; 笔记来源&#xff1a; 1.2023年中国增强现实&#xff08;AR&#xff09;行业研究报告 2.wiki/Augmented reality 3.In-Depth Review of Augmented Reality: Tracking Technologies, Development Tools, AR Displays, Collaborative AR…

js第二天

比较运算符 ==左右两边值是否相等 ===左右两边值和类型是否全相等 !==左右两边是否类型和值全不相等 undefin === null NaN === NaN(错误,NaN不等于任何值) =单等是赋值 ==双等是判断 ===三等是全等,开发中判断是否相等,一般用全等。 console.log 先比较a和a,相…

电脑添加虚拟网卡与ensp互联,互访

一、按照过程 1、打开设备管理器 2、点击网络适配器&#xff0c;点击左上角操作&#xff0c;点击“添加过时硬件” 3、下一页 4、选择“安装我手动从列表选择的硬件”&#xff0c;下一页 5、下拉&#xff0c;选择“网络适配器”&#xff0c;下一页 6、厂商选择“Microsoft”&…