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 二叉排序树的删除…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...
goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
