页面路由指在应用程序中实现不同页面之间的跳转和数据传递。OpenHarmony提供了Router模块,通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。
Router适用于模块间与模块内页面切换,通过每个页面的url实现模块间解耦。模块内页面跳转时,为了实现更好的转场动效场景不建议使用该模块,推荐使用Navigation。
页面跳转
页面跳转是开发过程中的一个重要组成部分。在使用应用程序时,通常需要在不同的页面之间跳转,有时还需要将数据从一个页面传递到另一个页面。
图1 页面跳转
Router模块提供了两种跳转模式,分别是router.pushUrl()和router.replaceUrl()。这两种模式决定了目标页面是否会替换当前页。
-
router.pushUrl():目标页面不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。
-
router.replaceUrl():目标页面会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。
说明:
- 创建新页面时,请参考构建第二个页面配置第二个页面的路由。
- 页面栈的最大容量为32个页面。如果超过这个限制,可以调用router.clear()方法清空历史页面栈,释放内存空间。
同时,Router模块提供了两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例。
-
Standard:多实例模式,也是默认情况下的跳转模式。目标页面会被添加到页面栈顶,无论栈中是否存在相同url的页面。
-
Single:单实例模式。如果目标页面的url已经存在于页面栈中,则会将离栈顶最近的同url页面移动到栈顶,该页面成为新建页。如果目标页面的url在页面栈中不存在同url页面,则按照默认的多实例模式进行跳转。
在使用Router相关功能之前,需要在代码中先导入Router模块。
import router from '@ohos.router';
import { BusinessError } from '@ohos.base';
import promptAction from '@ohos.promptAction';
- 场景一:有一个主页(Home)和一个详情页(Detail),希望从主页点击一个商品,跳转到详情页。同时,需要保留主页在页面栈中,以便返回时恢复状态。这种场景下,可以使用pushUrl()方法,并且使用Standard实例模式(或者省略)。
import router from '@ohos.router';
// 在Home页面中
function onJumpClick(): void {
router.pushUrl({
url: 'pages/Detail' // 目标url
}, router.RouterMode.Standard, (err) => {
if (err) {
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
return;
}
console.info('Invoke pushUrl succeeded.');
});
}
说明:
多实例模式下,router.RouterMode.Standard参数可以省略。
- 场景二:有一个登录页(Login)和一个个人中心页(Profile),希望从登录页成功登录后,跳转到个人中心页。同时,销毁登录页,在返回时直接退出应用。这种场景下,可以使用replaceUrl()方法,并且使用Standard实例模式(或者省略)。
import router from '@ohos.router';
// 在Login页面中
function onJumpClick(): void {
router.replaceUrl({
url: 'pages/Profile' // 目标url
}, router.RouterMode.Standard, (err) => {
if (err) {
console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
return;
}
console.info('Invoke replaceUrl succeeded.');
})
}
说明:
多实例模式下,router.RouterMode.Standard参数可以省略。
- 场景三:有一个设置页(Setting)和一个主题切换页(Theme),希望从设置页点击主题选项,跳转到主题切换页。同时,需要保证每次只有一个主题切换页存在于页面栈中,在返回时直接回到设置页。这种场景下,可以使用pushUrl()方法,并且使用Single实例模式。
import router from '@ohos.router';
// 在Setting页面中
function onJumpClick(): void {
router.pushUrl({
url: 'pages/Theme' // 目标url
}, router.RouterMode.Single, (err) => {
if (err) {
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
return;
}
console.info('Invoke pushUrl succeeded.');
});
}
- 场景四:有一个搜索结果列表页(SearchResult)和一个搜索结果详情页(SearchDetail),希望从搜索结果列表页点击某一项结果,跳转到搜索结果详情页。同时,如果该结果已经被查看过,则不需要再新建一个详情页,而是直接跳转到已经存在的详情页。这种场景下,可以使用replaceUrl()方法,并且使用Single实例模式。
import router from '@ohos.router';
// 在SearchResult页面中
function onJumpClick(): void {
router.replaceUrl({
url: 'pages/SearchDetail' // 目标url
}, router.RouterMode.Single, (err) => {
if (err) {
console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
return;
}
console.info('Invoke replaceUrl succeeded.');
})
}
以上是不带参数传递的场景。
如果需要在跳转时传递一些数据给目标页面,则可以在调用Router模块的方法时,添加一个params属性,并指定一个对象作为参数。例如:
import router from '@ohos.router';
class DataModelInfo {
age: number = 0;
}
class DataModel {
id: number = 0;
info: DataModelInfo|null = null;
}
function onJumpClick(): void {
// 在Home页面中
let paramsInfo: DataModel = {
id: 123,
info: {
age: 20
}
};
router.pushUrl({
url: 'pages/Detail', // 目标url
params: paramsInfo // 添加params属性,传递自定义参数
}, (err) => {
if (err) {
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
return;
}
console.info('Invoke pushUrl succeeded.');
})
}
在目标页面中,可以通过调用Router模块的getParams()方法来获取传递过来的参数。例如:
import router from '@ohos.router';
class InfoTmp {
age: number = 0
}
class RouTmp {
id: object = () => {
}
info: InfoTmp = new InfoTmp()
}
const params: RouTmp = router.getParams() as RouTmp; // 获取传递过来的参数对象
const id: object = params.id // 获取id属性的值
const age: number = params.info.age // 获取age属性的值
Copy to clipboardErrorCopied
页面返回
当用户在一个页面完成操作后,通常需要返回到上一个页面或者指定页面,这就需要用到页面返回功能。在返回的过程中,可能需要将数据传递给目标页面,这就需要用到数据传递功能。
图2 页面返回
在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
import router from '@ohos.router';
可以使用以下几种方式返回页面:
- 方式一:返回到上一个页面。
import router from '@ohos.router';
router.back();
这种方式会返回到上一个页面,即上一个页面在页面栈中的位置。但是,上一个页面必须存在于页面栈中才能够返回,否则该方法将无效。
- 方式二:返回到指定页面。
import router from '@ohos.router';
router.back({
url: 'pages/Home'
});
这种方式可以返回到指定页面,需要指定目标页面的路径。目标页面必须存在于页面栈中才能够返回。
- 方式三:返回到指定页面,并传递自定义参数信息。
import router from '@ohos.router';
router.back({
url: 'pages/Home',
params: {
info: '来自Home页'
}
});
这种方式不仅可以返回到指定页面,还可以在返回的同时传递自定义参数信息。这些参数信息可以在目标页面中通过调用router.getParams()方法进行获取和解析。
在目标页面中,在需要获取参数的位置调用router.getParams()方法即可,例如在onPageShow()生命周期回调中:
import router from '@ohos.router';
onPageShow() {
const params:Record<string,Object> = {'':router.getParams()}; // 获取传递过来的参数对象
const info:Object = params['']; // 获取info属性的值
}
说明:
当使用router.back()方法返回到指定页面时,该页面会被重新压入栈顶,而原栈顶页面(包括)到指定页面(不包括)之间的所有页面栈都将被销毁。
另外,如果使用router.back()方法返回到原来的页面,原页面不会被重复创建,因此使用@State声明的变量不会重复声明,也不会触发页面的aboutToAppear()生命周期回调。如果需要在原页面中使用返回页面传递的自定义参数,可以在需要的位置进行参数解析。例如,在onPageShow()生命周期回调中进行参数解析。
页面返回前增加一个询问框
在开发应用时,为了避免用户误操作或者丢失数据,有时候需要在用户从一个页面返回到另一个页面之前,弹出一个询问框,让用户确认是否要执行这个操作。
本文将从系统默认询问框和自定义询问框两个方面来介绍如何实现页面返回前增加一个询问框的功能。
图3 页面返回前增加一个询问框
系统默认询问框
为了实现这个功能,可以使用页面路由Router模块提供的两个方法:router.showAlertBeforeBackPage()和router.back()来实现这个功能。
在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
import router from '@ohos.router';
如果想要在目标界面开启页面返回询问框,需要在调用router.back()方法之前,通过调用router.showAlertBeforeBackPage()方法设置返回询问框的信息。例如,在支付页面中定义一个返回按钮的点击事件处理函数:
import router from '@ohos.router';
import { BusinessError } from '@ohos.base';
// 定义一个返回按钮的点击事件处理函数
function onBackClick(): void {
// 调用router.showAlertBeforeBackPage()方法,设置返回询问框的信息
try {
router.showAlertBeforeBackPage({
message: '您还没有完成支付,确定要返回吗?' // 设置询问框的内容
});
} catch (err) {
let message = (err as BusinessError).message
let code = (err as BusinessError).code
console.error(`Invoke showAlertBeforeBackPage failed, code is ${code}, message is ${message}`);
}
// 调用router.back()方法,返回上一个页面
router.back();
}
其中,router.showAlertBeforeBackPage()方法接收一个对象作为参数,该对象包含以下属性:
message:string类型,表示询问框的内容。 如果调用成功,则会在目标界面开启页面返回询问框;如果调用失败,则会抛出异常,并通过err.code和err.message获取错误码和错误信息。
当用户点击“返回”按钮时,会弹出确认对话框,询问用户是否确认返回。选择“取消”将停留在当前页目标页面;选择“确认”将触发router.back()方法,并根据参数决定如何执行跳转。
自定义询问框
自定义询问框的方式,可以使用弹窗或者自定义弹窗实现。这样可以让应用界面与系统默认询问框有所区别,提高应用的用户体验度。本文以弹窗为例,介绍如何实现自定义询问框。
在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
import router from '@ohos.router';
在事件回调中,调用弹窗的promptAction.showDialog()方法:
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';
import { BusinessError } from '@ohos.base';
function onBackClick() {
// 弹出自定义的询问框
promptAction.showDialog({
message: '您还没有完成支付,确定要返回吗?',
buttons: [
{
text: '取消',
color: '#FF0000'
},
{
text: '确认',
color: '#0099FF'
}
]
}).then((result:promptAction.ShowDialogSuccessResponse) => {
if (result.index === 0) {
// 用户点击了“取消”按钮
console.info('User canceled the operation.');
} else if (result.index === 1) {
// 用户点击了“确认”按钮
console.info('User confirmed the operation.');
// 调用router.back()方法,返回上一个页面
router.back();
}
}).catch((err:Error) => {
let message = (err as BusinessError).message
let code = (err as BusinessError).code
console.error(`Invoke showDialog failed, code is ${code}, message is ${message}`);
})
}
当用户点击“返回”按钮时,会弹出自定义的询问框,询问用户是否确认返回。选择“取消”将停留在当前页目标页面;选择“确认”将触发router.back()方法,并根据参数决定如何执行跳转。
命名路由
在开发中为了跳转到共享包中的页面(即共享包中路由跳转),可以使用router.pushNamedRoute()来实现。
在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
import router from '@ohos.router';
在想要跳转到的共享包页面里,给@Entry修饰的自定义组件命名:
// library/src/main/ets/pages/Index.ets
// library为新建共享包自定义的名字
@Entry({ routeName : 'myPage' })
@Component
export struct MyComponent {
}
配置成功后需要在跳转的页面中引入命名路由的页面:
import router from '@ohos.router';
import { BusinessError } from '@ohos.base';
const module = import('library/src/main/ets/pages/Index') // 引入共享包中的命名路由页面
@Entry
@Component
struct Index {
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text('Hello World')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({ top: 20 })
.backgroundColor('#ccc')
.onClick(() => { // 点击跳转到其他共享包中的页面
try {
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
})
} catch (err) {
let message = (err as BusinessError).message
let code = (err as BusinessError).code
console.error(`pushNamedRoute failed, code is ${code}, message is ${message}`);
}
})
}
.width('100%')
.height('100%')
}
}
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
-
HarmonOS基础技能
- HarmonOS就业必备技能
- HarmonOS多媒体技术
- 鸿蒙NaPi组件进阶
- HarmonOS高级技能
- 初识HarmonOS内核
- 实战就业级设备开发
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。