Harmony学习之页面路由与导航
一、场景引入
小明在上一篇文章中完成了登录界面的开发,现在他需要实现从登录页跳转到首页,并在跳转时传递用户信息。同时,他还需要处理页面返回、参数接收等场景。本篇文章将系统讲解HarmonyOS的页面路由与导航机制,帮助小明实现多页面应用的完整跳转流程。
二、路由模块导入与配置
1. 导入路由模块
在需要使用路由功能的页面中,首先需要导入router模块:
import router from '@ohos.router';
2. 页面注册配置
在resources/base/profile/main_pages.json文件中配置页面路径,确保所有需要跳转的页面都已注册:
{
"src": [
"pages/Index",
"pages/Login",
"pages/Home",
"pages/Detail"
]
}
三、页面跳转方式
1. pushUrl - 压栈跳转
pushUrl方法会将目标页面压入页面栈,保留当前页面状态,可以通过返回键或router.back()返回到当前页:
// 基本跳转
router.pushUrl({
url: 'pages/Home'
});
// 带参数跳转
router.pushUrl({
url: 'pages/Detail',
params: {
id: 123,
name: '商品详情'
}
});
2. replaceUrl - 替换跳转
replaceUrl方法会用目标页面替换当前页面,销毁当前页面资源,无法返回原页面:
// 登录成功后跳转到首页,销毁登录页
router.replaceUrl({
url: 'pages/Home'
});
3. 跳转模式
HarmonyOS提供两种跳转模式,通过router.RouterMode指定:
// Standard模式(默认):每次跳转都创建新实例
router.pushUrl({
url: 'pages/Detail',
params: { id: 123 }
}, router.RouterMode.Standard);
// Single模式:如果目标页已存在,则移动到栈顶
router.pushUrl({
url: 'pages/Detail',
params: { id: 456 }
}, router.RouterMode.Single);
跳转模式对比:
| 模式 | 行为 | 适用场景 |
|---|---|---|
| Standard | 每次跳转都创建新实例 | 商品详情页、新闻详情页 |
| Single | 复用已存在页面,移动到栈顶 | 设置页、个人中心页 |
四、参数传递与接收
1. 发送参数
在跳转时通过params属性传递参数:
// 登录页跳转到首页,传递用户信息
router.pushUrl({
url: 'pages/Home',
params: {
userId: '123456',
userName: '小明',
token: 'abcdefg'
}
});
2. 接收参数
在目标页面的生命周期方法中接收参数:
@Entry
@Component
struct Home {
@State userId: string = '';
@State userName: string = '';
// 推荐在aboutToAppear中接收参数
aboutToAppear() {
const params = router.getParams();
this.userId = params?.['userId'] || '';
this.userName = params?.['userName'] || '';
}
build() {
Column() {
Text(`欢迎回来,${this.userName}`)
.fontSize(20)
.margin({ bottom: 20 })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
3. 参数类型定义
建议定义参数类型接口,提高代码可读性和类型安全:
// 定义参数类型
interface UserInfo {
userId: string;
userName: string;
token: string;
}
// 发送参数
router.pushUrl({
url: 'pages/Home',
params: {
userId: '123456',
userName: '小明',
token: 'abcdefg'
} as UserInfo
});
// 接收参数
aboutToAppear() {
const params = router.getParams() as UserInfo;
this.userId = params.userId;
this.userName = params.userName;
}
五、页面返回与结果传递
1. 返回上一页
// 简单返回
router.back();
// 返回并传递结果
router.back({
result: {
status: 'success',
message: '操作成功'
}
});
2. 返回到指定页面
// 返回到指定页面
router.back({
url: 'pages/Home'
});
// 返回到指定页面并传递参数
router.back({
url: 'pages/Home',
params: {
refresh: true
}
});
3. 接收返回结果
在目标页面的onPageShow生命周期中接收返回结果:
@Entry
@Component
struct Home {
onPageShow() {
const result = router.getParams();
if (result?.refresh) {
// 刷新数据
this.loadData();
}
}
}
六、页面生命周期
1. 页面生命周期方法
被@Entry装饰的组件拥有完整的页面生命周期:
@Entry
@Component
struct DetailPage {
// 页面即将显示时触发
aboutToAppear() {
console.log('页面即将显示');
}
// 页面每次显示时触发
onPageShow() {
console.log('页面显示');
// 适合刷新数据
this.refreshData();
}
// 页面每次隐藏时触发
onPageHide() {
console.log('页面隐藏');
// 适合保存状态
this.saveState();
}
// 用户点击返回按钮时触发
onBackPress() {
console.log('返回按钮被点击');
// 返回true可拦截默认返回行为
return false;
}
// 页面即将销毁时触发
aboutToDisappear() {
console.log('页面即将销毁');
// 清理资源
this.cleanup();
}
}
2. 组件生命周期方法
普通组件(@Component装饰)的生命周期:
@Component
struct UserCard {
// 组件即将显示时触发
aboutToAppear() {
console.log('组件即将显示');
}
// 组件即将销毁时触发
aboutToDisappear() {
console.log('组件即将销毁');
}
// API 12新增:组件build完成后触发
onDidBuild() {
console.log('组件构建完成');
// 不建议在此修改状态变量
}
}
七、页面栈管理
1. 获取页面栈信息
// 获取页面栈长度
const length = router.getLength();
console.log(`当前页面栈长度:${length}`);
// 获取当前页面状态
const state = router.getState();
console.log('当前页面状态:', state);
2. 清空页面栈
页面栈最大容量为32个页面,超出时需要清理:
// 清空页面栈
router.clear();
八、实战案例:登录跳转完整流程
1. 登录页面(Login.ets)
import router from '@ohos.router';
@Entry
@Component
struct Login {
@State username: string = '';
@State password: string = '';
// 模拟登录成功
private loginSuccess() {
// 跳转到首页,传递用户信息
router.replaceUrl({
url: 'pages/Home',
params: {
userId: '123456',
userName: this.username,
token: 'login_token_123'
}
});
}
build() {
Column({ space: 20 }) {
TextInput({ placeholder: '请输入用户名' })
.width('90%')
.height(50)
.onChange((value: string) => {
this.username = value;
})
TextInput({ placeholder: '请输入密码' })
.width('90%')
.height(50)
.type(InputType.Password)
.onChange((value: string) => {
this.password = value;
})
Button('登录')
.width('90%')
.height(50)
.onClick(() => {
this.loginSuccess();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
2. 首页(Home.ets)
import router from '@ohos.router';
interface UserInfo {
userId: string;
userName: string;
token: string;
}
@Entry
@Component
struct Home {
@State userId: string = '';
@State userName: string = '';
@State token: string = '';
aboutToAppear() {
// 接收登录页传递的参数
const params = router.getParams() as UserInfo;
this.userId = params.userId;
this.userName = params.userName;
this.token = params.token;
console.log('用户信息:', params);
}
build() {
Column({ space: 20 }) {
Text(`欢迎回来,${this.userName}`)
.fontSize(24)
.fontWeight(FontWeight.Bold)
Button('查看详情')
.width(200)
.onClick(() => {
router.pushUrl({
url: 'pages/Detail',
params: {
id: 1001,
title: '商品详情'
}
});
})
Button('退出登录')
.width(200)
.backgroundColor(Color.Red)
.onClick(() => {
router.replaceUrl({
url: 'pages/Login'
});
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
3. 详情页(Detail.ets)
import router from '@ohos.router';
interface DetailParams {
id: number;
title: string;
}
@Entry
@Component
struct Detail {
@State id: number = 0;
@State title: string = '';
aboutToAppear() {
const params = router.getParams() as DetailParams;
this.id = params.id;
this.title = params.title;
console.log('详情页参数:', params);
}
build() {
Column({ space: 20 }) {
Text(`商品ID:${this.id}`)
.fontSize(18)
Text(`商品标题:${this.title}`)
.fontSize(18)
Button('返回')
.width(200)
.onClick(() => {
router.back({
result: {
refresh: true
}
});
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
九、最佳实践与注意事项
1. 参数传递优化
推荐做法:
- 传递最小必要数据(如ID),在目标页面重新查询完整数据
- 使用类型接口定义参数,提高代码可读性
- 避免传递大对象或函数
不推荐做法:
// 不推荐:传递大对象
router.pushUrl({
url: 'pages/Detail',
params: {
// 大对象数据...
}
});
2. 生命周期使用建议
| 生命周期方法 | 推荐使用场景 | 注意事项 |
|---|---|---|
aboutToAppear | 组件初始化、数据加载 | 适合首次加载数据 |
onPageShow | 页面显示时刷新数据 | 适合从后台返回时刷新 |
onPageHide | 保存页面状态、释放资源 | 避免耗时操作 |
aboutToDisappear | 清理定时器、取消订阅 | 禁止修改状态变量 |
3. 页面栈管理
- 页面栈最大容量为32个页面,超出时需要调用
router.clear()清理 - 使用
Single模式避免重复创建相同页面 - 及时清理不再需要的页面,释放内存
4. 错误处理
router.pushUrl({
url: 'pages/Detail',
params: { id: 123 }
}, (err) => {
if (err) {
console.error('跳转失败:', err);
// 处理错误,如跳转失败提示
return;
}
console.log('跳转成功');
});
十、总结与行动建议
核心要点回顾
- 路由模块导入:
import router from '@ohos.router' - 跳转方式:
pushUrl(压栈)、replaceUrl(替换) - 参数传递:通过
params传递,在目标页面router.getParams()接收 - 页面返回:
router.back()返回上一页,可传递返回结果 - 生命周期:
aboutToAppear、onPageShow、onPageHide等生命周期方法 - 页面栈管理:最大32个页面,使用
router.clear()清理
行动建议
- 动手实践:按照本文示例,完成登录-首页-详情页的完整跳转流程
- 参数传递练习:尝试传递不同类型的数据(字符串、数字、对象)
- 生命周期调试:在生命周期方法中添加日志,观察调用顺序
- 页面栈管理:创建多个页面,测试页面栈的压栈和出栈行为
- 错误处理:添加跳转失败的错误处理逻辑
通过本篇文章的学习,你已经掌握了HarmonyOS页面路由与导航的核心能力。下一篇文章将深入讲解网络请求与数据获取,帮助你实现从服务器获取数据并展示在界面上。
1527

被折叠的 条评论
为什么被折叠?



