HarmonyOS基础:鸿蒙系统组件导航Navigation
大家好!我是黑臂麒麟(起名原因:一个出生全右臂自带纹身的高质量程序员😏),也是一位6+(约2个半坤年)的前端;
学习如像练武功一样,理论和实践要相结合,学一门只是也是一样;
这里会用两周的时间把所学的常用ArkUI基础的常用组件输出在网;
如需深究可前往高级ArkTS系列课程;
望对学习鸿蒙小伙伴有所帮助;
介绍
Navigation组件:是路由导航根视图容器,一般作为Page页面(@Entry修饰符)的component作为根容器使用。在应用开发中起到了模块内和跨模块(对于在想要跳转到的共享包HAR/HSP页面里)的路由切换。
作为前端工程师,使用惯了vue-router/react-router,在使用Navigation有一定的学习成本,但使用起来后会发现其用法和vue-router/react-router的用法很像。
Navgiation
介绍
这里实现组件跳转要利用到Navigation组件、NavDestination组件、NavPathStack来实现跳转,这里简单介绍:
- Navigation路由导航根容器,包括标题栏、菜单栏、工具栏等。
- NavDestination是Navigation子页面的根容器用于承载子页面的一些特殊属性以及生命周期等,结构属性上跟Navigation一样
- NavPathStack管理路由容器
跳转
在使用navigation编写路由页面,一般navigation作为路由的根页面。在配合NavPathStack管理子路由NavDestination页面
private arr: number[] = [1, 2, 3];@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()private TooTmpItem: NavigationMenuItem = {'value': "", 'icon': "resources/base/media/ic_01_on.svg", 'action': ()=> {}}@State menuItems: Array<NavigationMenuItem> = [{value: 'menuItem1',icon: 'resources/base/media/ic_01_on.svg', // 图标资源路径action: () => {}}]// 根据name,跳转相应的子路由页面@BuilderpageMap(name: string){if (name === 'NavDestinationTitle1'){pageOneTmp()}else if(name === 'NavDestinationTitle2'){pageTweTmp()}else if(name === 'NavDestinationTitle3'){pageThreeTmp()}}build() {Column(){Navigation(this.pageInfos){TextInput({ placeholder: 'search...' })...List({ space: 12 }){ForEach(this.arr, (item: number)=> {ListItem() {Text("NavRouter" + item)....onClick(() => {this.pageInfos.pushPath({name: "NavDestinationTitle" + item})})}}, (item: number) => item.toString())}...}.title("根路由页面") // navigation的标题.titleMode(NavigationTitleMode.Mini) // 标题模式 可选值:Mini、Normal、Full.mode(NavigationMode.Stack) // navigation页面显示模式:Stack(非折叠屏手机模式/正常显示屏幕)、Split(折叠屏手机/屏幕较大)、auto(自动判断).menus([this.TooTmpItem, this.TooTmpItem, this.TooTmpItem]) // 导航栏菜单按钮.navDestination(this.pageMap) // 路由容器.toolbarConfiguration([this.TooTmp, this.TooTmp, this.TooTmp]) // tabbar的配置}}@Component
export struct pageOneTmp {@Consume('pageInfos') pageInfos: NavPathStack;build() {NavDestination(){Column(){Text('NavDestinationContent1')}.width('100%').height('100%')}.title('子页面1').onBackPressed(() => {const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))return true})}
}@Component
export struct pageTweTmp {@Consume('pageInfos') pageInfos: NavPathStack;build() {NavDestination(){Column(){Text('NavDestinationContent2')}.width('100%').height('100%')}.title("子页面2").onBackPressed(() => {const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))return true})}
}
在Navigtion的属性navDestination,我们传入路由容器,根据name不同,渲染不同的页面。

子页面之间跳转
介绍子页面跳转之前会用到系统路由表,我们先介绍:
- 在跳转目标模块的配置文件module.json5添加路由表配置:
{"module" : {"routerMap": "$profile:route_map"}
}
- 添加完路由配置文件地址后,需要在工程resources/base/profile中创建route_map.json文件。添加如下配置信息:
{"routerMap": [{"name": "PageOne", // 跳转页面名称。"pageSourceFile": "src/main/ets/pages/PageOne.ets", // 跳转目标页在包内的路径,相对src目录的相对路径。"buildFunction": "PageOneBuilder", // 跳转目标页的入口函数名称,必须以@Builder修饰。"data": { // 应用自定义字段。可以通过配置项读取接口getConfigInRouteMap获取。"description" : "this is PageOne"}}]
}
- 在跳转目标页面中,需要配置入口Builder函数,函数名称需要和route_map.json配置文件中的buildFunction保持一致,否则在编译时会报错。
// 跳转页面入口函数
@Builder
export function PageOneBuilder() {PageOne()
}@Component
struct PageOne {pathStack: NavPathStack = new NavPathStack()build() {NavDestination() {}.title('PageOne').onReady((context: NavDestinationContext) => {this.pathStack = context.pathStack})}
}
- 通过pushPathByName等路由接口进行页面跳转。(注意:此时Navigation中可以不用配置navDestination属性)。
@Entry
@Component
struct Index {
pageStack : NavPathStack = new NavPathStack();build() {Navigation(this.pageStack){}.onAppear(() => {this.pageStack.pushPathByName("PageOne", null, false);}).hideNavBar(true)
}
}
上面就是配置系统路由表,然后就能实现子页面之间的跳转,下面是完整代码。
// PageOne.ets
@Builder
export function PageOneBuilder(name: string, param: Object){PageOne()
}@Component
export struct PageOne {pageInfos: NavPathStack = new NavPathStack()build() {NavDestination(){Column() {Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule }).onClick(() => {let tmp = new TmpClass();this.pageInfos.pushPathByName('pageTwo', tmp)})}.width('100%').height('100%')}.title('pageOne').onReady((context: NavDestinationContext) => {this.pageInfos = context.pathStack;})}
}
PageTwo.ets
@Builder
export function PageTwoBuilder(name: string, param: Object){PageTwo()
}
@Component
export struct PageTwo{pathStack: NavPathStack = new NavPathStack();build() {NavDestination() {Column(){Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule }).onClick(() => {console.info("1231231")this.pathStack.pushPathByName('pageOne', null)})}.width('100%').height('100%')}.title('pageTwo').onReady((context: NavDestinationContext) => {this.pathStack = context.pathStack;console.log('current page config info is' + JSON.stringify(context.getConfigInRouteMap()))})}
}
在我们配置了系统路由后,上面pageOne和pageTwo子页面我们定义NavPathStack路由栈,然后在onReady中获取到路由栈,然后在利用pushPtahName的方法进行页面跳转。
拦截
NavPathStack提供了setInterception方法,用于设置Navigation页面跳转拦截回调。该方法需要传入一个NavigationInterception对象,该对象包含三个回调函数:
this.pageInfos.setInterception({// 页面跳转前回调,允许操作栈,在当前跳转生效。willShow: (form: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar", operation: NavigationOperation, animated: boolean) => {if (typeof to === "string") {console.log("target page is navigation home page.");return}// 将跳转PageTwo的路由重定向PageOnelet target: NavDestinationContext = to as NavDestinationContext;if (target.pathInfo.name === "NavDestinationTitle2"){target.pathStack.pop();target.pathStack.pushPath({name: "NavDestinationTitle3"}, false)}},// 页面跳转后回调,在该回调中操作栈会在下一次跳转生效。didShow: (){},// Navigation单双栏显示状态发生变更时触发该回调。modeChange: () {}
})
参数获取
NavPathStack通过Get相关接口去获取页面的一些参数。
// 获取栈中所有页面name集合
this.pageStack.getAllPathName()
// 获取索引为1的页面参数
this.pageStack.getParamByIndex(1)
// 获取PageOne页面的参数
this.pageStack.getParamByName("PageOne")
// 获取PageOne页面的索引集合
this.pageStack.getIndexByName("PageOne")
页面返回
NavPathStack通过Pop相关接口去实现页面返回功能。
// 返回到上一页
this.pageStack.pop()
// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne")
// 返回到索引为1的页面
this.pageStack.popToIndex(1)
// 返回到根首页(清除栈中所有页面)
this.pageStack.clear()
子页面
页面生命周期
子页面里比较重要的概念就是生命周期,其生命周期大致可分为三类,自定义组件生命周期、通用组件生命周期和自有生命周期。其中,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:自定义组件析构销毁之前执行,不允许在该方法中改变状态变量。
结语
本篇文章的内容结束了。文章有不对或不完整的地方,望多指点;
望更多小伙伴们加入harmonyOS开发大家庭,壮大生态圈,让鸿蒙更好,让国产手机(物联网)系统更强大。
如对你学习有所帮助,希望可爱你动动小手,关注、点赞、收藏;
相关文章:
HarmonyOS基础:鸿蒙系统组件导航Navigation
大家好!我是黑臂麒麟(起名原因:一个出生全右臂自带纹身的高质量程序员😏),也是一位6(约2个半坤年)的前端; 学习如像练武功一样,理论和实践要相结合࿰…...
【K8S问题系列】Kubernetes 中 Pod 无法通过 Service 名称访问服务的 DNS 解析失败【已解决】
在 Kubernetes 中,Service 提供了一种稳定的方式,通过名称访问一组 Pod。当其他 Pod 无法通过 Service 名称访问服务,并且出现 DNS 解析失败时,通常会导致应用无法正常工作。本文将详细分析此问题的常见原因及其解决方案。 一、问…...
【下载工具】Internet Download Manager下载器介绍
Internet Download Manager(简称IDM)作为一款功能强大的下载管理软件,以其高效、稳定的特点受到了广大用户的青睐。本文将为您详细介绍IDM的功能特性以及具体的使用方法。 功能特性 加速下载:IDM通过多线程下载技术,…...
如何打开/关闭 GitLab 的版本检查功能?
本文分享如何打开/关闭 GitLab 的版本检查功能。 极狐GitLab 是 GitLab 的中国发行版【https://dl.gitlab.cn/ncecn6kb】,中文版本对中国用户更友好,文章以私有化部署的极狐GitLab 实例来演示版本检查功能的开启和关闭。强烈不建议关闭该功能࿰…...
java-web-day13-事务管理+spring aop
事务管理: 事务回滚 默认情况下,只有出现runtimeException(运行时异常)才回滚, 而如果出现其他异常,例如受检异常, 就不会回滚事务, 不过可以加上rollbackfor属性用于控制出现何种异常类型, 回滚事务 事务传播: 当一个事务方法被另一个事务方法调用时, 这个事务方法应该如何进行…...
MySQL详细安装教程
一、从MySQL官网安装 可以翻译成中文看起来就舒服多了 下载并打开安装包,能看到版本是8.0.36,双击运行或者右键选择打开,打开后是一个安装向导,这个安装向导会先帮我们安装一个 mysql-installer 的程序,再通过该程序安…...
文件系统和日志管理
一、文件系统 1.概述 文件系统:文件系统提供了一个接口,用户用来访问硬件设备(硬盘)。硬件设备上对文件的管理。文件存储在硬盘上,硬盘最小的存储单位是512字节(扇区)。文件在硬盘上的最小存储…...
【LeetCode】【算法】208. 实现 Trie (前缀树)
LeetCode 208. 实现 Trie (前缀树) 题目描述 Trie(发音类似 “try”)或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。 请你实现 Trie 类&…...
libaom 源码分析:帧间运动矢量预测
AV1 帧间运动矢量预测原理 运动矢量可以被相邻块预测,这些相邻块可以是空域相邻块,或位于参考帧中的时域相邻块;通过检查所有这些块,将确定一组运动矢量预测器,并用于编码运动矢量信息。空域运动矢量预测 两组空域相邻块可以被利用寻找空域 MV 预测器,第一组包括当前块的…...
Android TextView自动换行文本显示不全解决
某些情况下,TextView自动换行后,会出现每行结尾处显示不全的问题, 如图: 常见解决方案: 设置TextView的“ellipsize”属性为“end” 实测无效!将TextView外部的Layout改为RelativeLayout 实测无效&…...
【LeetCode】【算法】394. 字符串解码
LeetCode 394. 字符串解码 题目描述 给定一个经过编码的字符串,返回它解码后的字符串。 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。 你可以认为输入字符串总是有效的;输入字…...
最新整理:Selenium自动化测试面试题
1.selenium中如何判断元素是否存在? find_elements查找到的元素个数为0,find_element报错意味着元素不存在 2.如何判断元素是否出现? 判断元素是否出现,存在两种情况,一种是该元素压根就没有,自然不会出现;另外一种是有这样的…...
外包干了2年,快要废了。。。
先说一下自己的情况,普通本科,在外包干了2年多的功能测试,这几年因为大环境不好,我整个人心惊胆战的,怕自己卷铺盖走人了,我感觉自己不能够在这样蹉跎下去了,长时间呆在一个舒适的环境真的会让一…...
乐尚代驾十订单支付seata、rabbitmq异步消息、redisson延迟队列
账单信息 司机结束代驾之后,生成账单(包含账单信息和分账信息)司机发送账单给乘客乘客获取账单之后,进行支付 获取账单信息 order_bill表记录的账单信息,我们直接获取即可 Operation(summary "根据订单id获取…...
HCIP--3实验- 链路聚合,VLAN间通讯,Super VLAN,MSTP,VRRPip配置,静态路由,环回,缺省,空接口,NAT
学习目标: 链路聚合VLAN间通讯Super VLANMSTPVRRPip配置,静态路由,环回,缺省,空接口NAT 学习内容: 实验拓扑实验需求实验需求分析实验配置内容 (每一个设备的每一步操作)实验结果验证 1.实验拓扑 搭建 …...
Apple提出MM1.5:多模态大型语言模型微调的方法、分析和见解_mm1.5 模型下载
摘要 我们介绍了 MM1.5,一个新的多模态大型语言模型 (MLLM) 家族,旨在增强在富文本图像理解、视觉参照和定位以及多图像推理方面的能力。 在 MM1 架构的基础上,MM1.5 采用以数据为中心的模型训练方法,系统地探索了整个模型训练生…...
【毫米波雷达(三)】汽车控制器启动流程——BootLoader
汽车控制器启动流程——BootLoader 一、什么是Bootloader(BT)?二、FBL、PBL、SBL、ESS的区别三、MCU的 A/B分区的实现 一、什么是Bootloader(BT)? BT就是一段程序,一段引导程序。它包含了启动代码、中断、主程序等。 雷达启动需要由BT跳转到…...
AI 搜索来势汹汹,互联网将被颠覆还是进化?
最近,美国新闻集团起诉了知名 AI 搜索引擎 Perplexity AI。也许你会想,这不就是又一起“AI 惹官司”吗?其实,这次情况不太一样,甚至可能会改变我们未来上网的方式! 争议的焦点是什么?是未来的 …...
《二分查找算法:在有序数组中搜索目标值》
目录 一、问题分析 二、二分查找算法原理 三、代码实现 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,我们要写一个函数来搜索 nums 中的 target,如果目标值存在就返回它的下标,否则返回 -1。 …...
【万字总结】数据结构常考应用大题做法画法详解_树_哈希表_图_排序大总结
文章目录 1.树相关应用大题1.1 已知二叉树的中序序列和前序or中序,画出二叉树1.2 二叉树的遍历、树的遍历、森林的遍历总结1.3二叉树与森林之间的转换1.3.1 已知树的先序序列和中序序列,画出森林 1.4 二叉树的线索化1.5 二叉排序树1.5.1 二叉排序树的删除…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
