重生之我在大学自学鸿蒙开发第六天-《组件导航》
- 个人主页:VON
- 文章所属专栏:从0开始的开源鸿蒙6.0.0
- 个人抖音:清洒
目录
一、前言
二、实践
2.1、Tabs
2.1.1、TabContent组件
2.1.2、自定义导航页签栏
2.1.3、使用自定义tabBar
2.1.4、拓展
2.2.1、实现知识地图页面导航
2.2.2、 实现文章详情页跳转
核心组件结构
属性与控制器
构建UI布局
WebView功能配置
数据流逻辑
核心差异
总结
2.2.3、实现Banner跳转
三、测试
四、总结
一、前言
不管是哪种开发方式都离不开导航,就像我们用的手机,平板,电脑等,都需要用到导航功能,在APP或者网页中通过点击图标实现的页面跳转就是我们所要学习的组件导航,学完组件导航估计就可以实现简单拿的APP开发了,准备明天整理一下基础篇的知识,下周开始自己设计项目,为了应对接下来的比赛。
二、实践
本章节内容参考官方链接
通过结构化数据构建页面-HarmonyOS应用开发快速入门-Codelabs-华为开发者联盟
2.1、Tabs
官方解释:
当页面信息较多时,为了让用户能够聚焦于当前显示的内容,需要对页面内容进行分类,提高页面空间利用率。Tabs组件可以在一个页面内快速实现视图内容的切换,一方面提升查找信息的效率,另一方面精简用户单次获取到的信息量,接下来逐步了解如何使用Tabs组件。
这里开始将重点转为default模块这里是在index中书写的代码
import { CourseLearning } from 'learning';
import { QuickStartPage } from 'quickstart';
import { KnowledgeMap, KnowledgeMapContent } from 'map';@Entry
@Component
struct Index {build() {Tabs(){}.scrollable(false).vertical(false).divider({strokeWidth: 0.5,color: '#0D182431'}).backgroundColor('#F1F3F5').padding({ top: 36, bottom: 28 })}
}
属性解释:
使用scrollable属性设置为false限制Tabs无法横向滑动切换页签,使用vertical属性设置为false限制Tabs为非纵向导航条,使用divider属性将TabBar导航页签栏与TabContent进行分割,设置Tabs整体的背景颜色为'#F1F3F5',同时使用padding属性进行内容的避让。
这里可以根据解释来进行自定义美化格式
2.1.1、TabContent组件
通过TabContent组件可以完成跳转功能,这里的参数也是一目了然
2.1.2、自定义导航页签栏
导航栏的样式可以进行自定义,包括选中和未选中的样式是不同的这里我们平时用的APP中就可以体现出来,这里直接把完整的函数让大家进行参考
@BuildertabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {Column() {Image(this.currentIndex === targetIndex ? selectedIcon : unselectIcon).width(24).height(24)Text(title).fontFamily('HarmonyHeiTi-Medium').fontSize(10).fontColor(this.currentIndex === targetIndex ? '#0A59F7' : 'rgba(0,0,0,0.60)').textAlign(TextAlign.Center).lineHeight(14).fontWeight(500)}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).onClick(() => {this.currentIndex = targetIndex;this.tabsController.changeIndex(targetIndex);})}
2.1.3、使用自定义tabBar
将Tabs中的跳转换成我们自己写的页面,这三个页面之前的文章中都带领大家实现过
2.1.4、拓展
这里官网给出了拓展方案,说实话这里我并不是很清楚
官网解释:
TabsController是Tabs组件的控制器,用于控制Tabs组件进行页签切换。开发者后续可以通过TabsController的changeIndex()方法来实现跳转至指定索引值对应的TabContent内容。
2.2、Navigation
还是老规矩,先查看官方的解释
官方解释:
通过Tabs构建了页面之间平级的切换,但对于一些需要点击进入下一层级的页面,例如点击列表项进入列表项的详情页,这种还需要借助Navigation实现。
简单来说就是页面间的跳转用Tabs,组件间的跳转用Navigation,就像上篇文章中的知识地图详情页就需要通过Navigation来实现跳转。
话不多说直接开始实现
2.2.1、实现知识地图页面导航
先创建一个路由栈
@Provide('knowledgeMapPageStack') knowledgeMapPageStack: NavPathStack = new NavPathStack();
这里由于我们改造的是map模块,所以路由栈在pages中添加
官方解释:
在KnowledgeMap页面中定义路由栈。通过创建NavPathStack实例并定义为@Provide类型的状态变量来进行路由栈的定义。Navigation有属于自己的路由栈,可以用于路由的前进、回退、路由历史记录的保存、路由参数的保存与获取。所以首先需要创建一个路由栈。
注意此处采用@Provide的方式进行定义,由于之后会将该路由栈的数据传递给跳转后的后代组件,为了方便后代组件的获取,所以此处采用了@Provide的方式进行定义。
这里我们使用Navigation要包裹Scroll组件,优先级是最高的。如果有参数不明白的可以看下注释
接下来改造下NavBarItem,这里说下我的理解,可能是因为这里是view中的文件,所以需要使用祖代组件传递过来的路由栈数据
第二处改造的地方就是点击事件来进行页面的跳转,注意NavBarItem文件
接下来实现下高亮提示功能
这里的因为是动态改变的所以用Link,state好像是只能用于静态数据的定义,核心逻辑就是通过改变currentNavBarIndex的值从而进行的判断,然后根据currentNavBarIndex进行渲染
官方解释:
@Link的方式,是由于需要在NavBarItem组件中对值进行修改,并将修改同步到KnowledgeMap组件中。
这里先在KnowledgeMap组件中定义好要传入的参数,因为是根据是否选中来进行渲染的
可以看下NavBarItem中接收的参数信息,只需要传入2个参数即可,这里强调一下数据都是从父组件中获取的,目前我感觉是这样的
还是在这个页面,来实现页面跳转功能,根据传入的name来进行判断展示那个页面
这里引入的时候别忘了用import导入一下
最后改造下KnowledgeMapContent页面即可,这里改造就容易了,只需要改页面能够展示出来即可,这里用NavDestination包裹一下就行了,别忘了清除默认标题
2.2.2、 实现文章详情页跳转
这部分内容有些复杂,我就尽量根据文档来加上我自己的理解分析一下吧
先分析一下页面的设计,这里的内容是通过网页获取的,这里忘记的可以看下第四篇文章重生之我在大学自学鸿蒙开发第四天-《ArkWeb页面适配》-CSDN博客
接着在ArticleDetailPage文件内定义出WebComponent组件用以加载Web资源,这部分内容我不太能解释,交给ai解释下
@Component
struct WebComponent {@Prop articleDetail: ArticleClass | null;private webviewController: webview.WebviewController = new webview.WebviewController();build(){Column() {Web({ src: this.articleDetail?.webUrl, controller: this.webviewController }).darkMode(WebDarkMode.Auto).domStorageAccess(true).zoomAccess(true).fileAccess(true).mixedMode(MixedMode.All).cacheMode(CacheMode.None).javaScriptAccess(true).width('100%').layoutWeight(1)}}
}
核心组件结构
该代码定义了一个名为
WebComponent
的ArkUI组件(使用@Component
装饰器),主要用于嵌入并控制一个WebView页面。属性与控制器
@Prop articleDetail: ArticleClass | null
接收父组件传递的文章详情数据,包含网页URL(webUrl
)等字段。@Prop
表示该属性支持单向绑定。private webviewController: webview.WebviewController
创建WebView控制器实例,用于管理WebView的行为(如加载、导航等)。构建UI布局
在
build()
方法中:
- 使用
Column
容器纵向布局,内部嵌套Web
组件。Web
组件的src
绑定到articleDetail.webUrl
,动态加载目标网页。controller
绑定到webviewController
,实现对WebView的编程控制。WebView功能配置
通过链式调用配置WebView的行为:
.darkMode(WebDarkMode.Auto)
:根据系统设置自动切换深色模式。.domStorageAccess(true)
:启用DOM存储(如LocalStorage)。.zoomAccess(true)
:允许手势缩放。.fileAccess(true)
:允许访问本地文件。.mixedMode(MixedMode.All)
:允许加载HTTP/HTTPS混合内容。.cacheMode(CacheMode.None)
:禁用缓存(每次重新加载)。.javaScriptAccess(true)
:启用JavaScript执行。.width('100%')
:宽度占满父容器。.layoutWeight(1)
:在父布局中分配剩余空间(避免被其他组件挤压)。数据流逻辑
父组件通过
articleDetail
属性传递数据,当webUrl
更新时,Web
组件会自动加载新URL内容。
这里传入的参数类型是我们之前定义的ArticleClass 类型的数据
export class ArticleClass {id: string = '';imageSrc: string = '';title: string = '';brief: string = '';webUrl: string = '';constructor(id: string, imageSrc: string, title: string, brief: string, webUrl: string) {this.id = id;this.imageSrc = imageSrc;this.title = title;this.brief = brief;this.webUrl = webUrl;}
}
准备工作完成开始进行路由跳转逻辑的实现,这里我们需要实现两个页面的跳转
完成点击技术文章跳转到技术文章详情页的逻辑,首先拿到页面栈信息,并为EnablementItem和TutorialItem添加点击事件,使用pushPathByName()传递参数。
这里因为是点击事件所以在Item中加一个点击事件就可以了
获取到路由栈,并通过getParamByName()获取到参数信息并设置给articleDetail,最后在build()内包裹一个NavDestination
这里普及一下NavDestination和Navigation区别,相信大家都发现了这里使用的不同,我也是注意了下,大家可以看下这段解释,就是范围大小的不同
NavDestination 与 Navigation 的区别
NavDestination 是 Android Jetpack Navigation 组件中的一个类,代表导航图中的单个目标(如 Fragment、Activity 或其他自定义目标)。它包含目标的路由信息(如 ID、参数等),用于导航时的具体跳转逻辑。
Navigation 是 Android Jetpack 提供的一个完整框架,用于简化应用内的页面跳转和导航逻辑。它包含导航图(NavGraph)、控制器(NavController)、目标(NavDestination)等核心组件,提供统一的 API 管理页面流转。
核心差异
1. 角色不同
- NavDestination:导航图中的具体目标节点,定义单个页面的属性和行为(如参数、动画等)。
- Navigation:整个导航框架的统称,涵盖导航图、控制器、目标管理等整套解决方案。
2. 功能范围
- NavDestination:
- 存储目标的路由信息(如
android:id
)。- 支持通过
arguments
传递参数。- 可自定义深度链接(DeepLink)。
- Navigation:
- 提供
NavController
处理跳转逻辑(如navigate()
)。- 通过 XML 或编程方式定义导航图(NavGraph)。
- 支持条件导航、返回栈管理等高级功能。
总结
- NavDestination 是导航框架中的原子单位,代表具体页面。
- Navigation 是管理这些页面及其跳转关系的框架。
两者是部分与整体的关系,协作完成应用内导航功能。
最后实现下返回键的逻辑功能就完成了
2.2.3、实现Banner跳转
这里要先创建好BannerDetailPage空页面
获取路由栈中的数据,使用@State定义出需要进行赋值的数据,并定义出Web控制器。
开始在Banner中进行调用,这里是通过点击图片进行跳转的
三、测试
可以看到之前看不到的页面现在都可以进行展示了,说明我们测试成功
四、总结
说实话这部分需要不断巩固,这里只是对照源码进行编写和分析,如果让我自己写肯定不会思路如此清晰,这里需要仔细琢磨下,希望大家可以认真观看官方文档,官方文档更详细一点,包含了很多名词的解释。