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页面路由与导航的核心能力。下一篇文章将深入讲解网络请求与数据获取,帮助你实现从服务器获取数据并展示在界面上。