前言
最近一段时间,基于HarmonyOS NEXT鸿蒙原生应用非常引人瞩目。在鸿蒙系统中,页面路由机制是连接应用各页面的关键组成部分。本文将深入探讨鸿蒙系统的页面路由,揭示其工作原理、特点以及在应用开发中的实际应用。
一、什么是页面路由?
页面路由指在应用程序中实现不同页面之间的跳转和数据传递。
页面跳转是开发过程中的一个重要组成部分。在使用应用程序时,通常需要在不同的页面之间跳转,有时还需要将数据从一个页面传递到另一个页面。
二、鸿蒙提供的页面路由API
鸿蒙现在提供了两种页面路由的API,一种是router,一种是navigation,下文将详细介绍下其使用方法和优缺点。
鸿蒙系统的页面路由基于一种轻量级的栈式管理结构。每个页面都有一个唯一的标识符,当页面切换时,页面路由根据标识符入栈或出栈,实现页面的切换和管理。
注:以下API和代码都基于HarmonyOS NEXT API11。
1、router
1.1 API介绍
1.1.1 两种跳转模式
Router模块提供了两种跳转模式,分别是router.pushUrl()和router.replaceUrl()。这两种模式决定了目标页是否会替换当前页。
- router.pushUrl():目标页不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。
·router.replaceUrl():目标页会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。
1.1.2 两种实例模式
Router模块提供了两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例。
- Standard:标准实例模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。
- Single:单实例模式。即如果目标页的url在页面栈中已经存在同url页面,则离栈顶最近的同url页面会被移动到栈顶,并重新加载;如果目标页的url在页面栈中不存在同url页面,则按照标准模式跳转。
1.1.3 跳转或返回指定页面的两种方式
我们想跳转和返回某个页面的时候,可以通过两个方式告诉我们要跳转或返回哪个页面;
- URL:就是当前页面相对要跳转页面的相对路径。比如:
router.pushUrl({
url: 'pages/Theme' // 目标url
}
//返回目标页
router.back({
url: 'pages/Theme' // 目标url
}
这种方式比较适合module内跳转,要是需要跨module的话这种方式就不太适合了,需要用下面routeName的方式:
- routeName:就是命名路由,其实就是给每一个页面一个唯一的标识符,设置这个routeName的方法如下:
@Entry({ routeName: 'myPage' })
@Component
export struct MyComponent {
build() {
}
}
使用命名路由进行跳转的时候,需要先引用命名路由的页面,跳转或返回代码如下:
router.pushNamedRoute({name: 'myPage'})
1.1.4 带参数跳转或返回
在跳转和返回的时候加上要携带的参数,参数的类型可以是基本数据类型,也可以是自定义的数据模型,代码如下:
//带自定义参数进行调转
let paramsInfo: DataModel = {
id: 123,
info: {
age: 20
}
};
router.pushUrl({
url: 'pages/Detail', // 目标url
params: paramsInfo // 添加params属性,传递自定义参数
}
//带参数返回指定页面
router.back({
url: 'pages/Home',
params: {
info: '来自Home页'
}
});
在目标页面中,可以通过调用Router模块的getParams()方法来获取传递过来的参数。
1.2 router的优点和缺点
在实际开发和使用中,也发现了router的优点和缺点,如下:
1.2.1 优点
使用比较方便,简单便捷。
1.2.2 缺点
如果你的应用没有太复杂的页面栈管理,那router将会非常适合你,但如果你的应用页面栈管理比较复杂,那router现有的API将无法满足你的需求。
- 没有返回指定页面的API,如果页面栈里面有多个相同routeName的页面时,那返回这个routeName的页面只能返回到最上面一个;目前很多应用都在使用混合开发模式,使用这种模式开发的APP在使用的过程中肯定会产生很多webview容器页面,这些页面有同样的routeName,会让你返回指定页面的操作变得很麻烦,如果页面栈中有10个routeName相同的页面,我向返回到其中的第五个页面,使用router的话只能连续调用router.back()5次。
- 没有清除掉页面栈中页面的API。无法静默的清除掉一个非页面栈栈顶的页面。
- 无法在外部获取跳转时传进页面的参数。有时候我们会根据传进页面的参数对有着相同routeName的页面进行区分,不能在外部获取到页面的参数,而HarmonyOSNEXT的语言特性又让我们拿不到页面对象,这样会很麻烦。
2、Navigation
Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。
Navigation组件有诸多功能,由于本文篇幅有限,所以只讲一下其中的页面路由功能。
2.1 API介绍
2.1.1 使用前准备工作
Navigation比router的使用要复杂,我们需要在根页面上加上Navigation组件,给所有的跳转目标页都加上NavDestination组件,代码如下:
@Entry
@Component
struct Index {
@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack();//导航栈管理类对象
@Builder
//注册跳转目标页,所有的跳转目标页都在在此注册
PagesMap(name: string) {
//通过判断目标页的唯一标识符,去调用相应目标页的构造方法
if (name == 'Page01') {
Page01()
} else if (name == 'Page02') {
Page02(); //相应目标页的构造方法
}
}
build() {
Navigation(this.pageInfos) { //用navigation组件把UI布局包起来
Button('push Page')
.width('80%')
.onClick(() => {
this.pageInfos.pushPathByName('Page01', ''); //进行跳转
})
}
.navDestination(this.PagesMap)//在此把注册跳转目标页的方法传给navigation
}
}
然后在跳转目标页要加上NavDestination组件,代码如下:
@Component
struct Page01 {
@Consume('pageInfos') pageInfos: NavPathStack; //接收并同步导航栈管理类对象
build() {
NavDestination() { //用NavDestination组件把UI布局包起来
}
.title('Page01') //设置页面唯一标识符
}
}
这样完成注册之后,所有的注册上的页面都可以用NavPathStack进行互相跳转。
2.1.2 页面跳转
所有对navigation页面栈的操作都要基于导航栈管理类对象pageInfos: NavPathStack去操作,我们可以用每个页面都有的pageInfos属性去进行页面栈管理,建议把其用单例保存起来,这样在工程任何地方都可以进行页面栈管理操作了。
页面跳转的是通过 this.pageInfos.pushPathByName('Page01', ''); 进行的。
如果想要带参数的话,可以这么带参数,参数的类型可以是基本数据类型,也可以是自定义的数据模型。this.pageInfos.pushPathByName('Page01', {pageID:'110'});
也有像router那样的replace方法让目标页替换当前页,并销毁当前页。
2.1.3 页面返回
页面返回的api如下:
this.pageInfos.pop(); 返回上一个页面;
this.pageInfos.popToName('Page01'); 返回页面栈中Name为Page01的页面;
this.pageInfos.popToIndex(1); 返回页面栈中下标为1的页面;
this.pageInfos.clear();清除页面栈中的所有页面;
2.1.4 获取导航栈中页面的参数
我们跳转到目标页时传的参数是和导航栈中的页面绑定的,我们可以通过一些API获取页面栈中页面的参数;
this.pageInfos.getAllParams(); 返回值为数组,返回页面栈中所有页面的参数;
this.pageInfos.getParamsByName(); 返回值为数组,返回页面栈中所有Name为入参的页面的参数 ;
this.pageInfos.getParamByIndex(); 返回下标为入参的页面的参数;
2.2 Navigation的优缺点
2.2.1 优点
各种API比较齐全,能利用其API进行各种各样复杂的页面栈管理。
2.2.2 缺点和问题
1、使用起来比较繁琐;
2、有时候在根页面注册一个新的页面会导致白屏,没搞明白为什么,但是可以通过加routeName去解决,不过有时候加routeName也不能解决问题,这时就可以尝试通过修改目标页的类名去解决问题;
3、在页面里使用NavDestination组件会导致页面的onPageShow和onPageHide两个生命周期方法失效。解决办法是NavDestination组件也有onPageShow和onPageHide两个生命周期方法,可以把相关逻辑迁移到这两个方法中来;
4、现在只能获取导航栈中的页面的参数,而不能修改。
三、总结
关于鸿蒙系统的页面路由就介绍完了,其相关API的能力和优劣也做了分析。
笔者其实更推荐使用Navigation组件去进行页面路由,因为其相关的API更加全面和强大,能满足我们的绝大部分需求。
更现实一点的原因是华为已经宣布停止router相关API的演进了,未来的主流肯定是Navigation。
但是如果你应用的页面路由真的非常的简单,不需要什么复杂操作,那使用更加简单快捷的router就比较适合了。
如果大家还没有掌握鸿蒙,现在想要在最短的时间里吃透它,我这边特意整理了《鸿蒙语法ArkTS、TypeScript、ArkUI、教学视频》以及《鸿蒙生态应用开发白皮书V2.0PDF》《鸿蒙开发学习手册》(共计890页)鸿蒙相关开发资料等…希望对大家有所帮助:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
OpenHarmony APP开发教程步骤:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
鸿蒙生态应用开发白皮书V2.0PDF:https://docs.qq.com/doc/DZVVkRGRUd3pHSnFG
南北双向高工技能基础:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
应用开发中高级就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
全网首发-工业级 南向设备开发就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
《鸿蒙开发学习手册》:
如何快速入门:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……