鸿蒙原生开发手记:徒步迹 - 页面路由与Navigation导航
·
鸿蒙原生开发手记:徒步迹 - 页面路由与Navigation导航
掌握鸿蒙 Navigation 路由系统,实现页面间流畅跳转
一、前言
页面路由是 App 的基础骨架,决定了用户如何在不同页面间导航。HarmonyOS 提供了两套路由方案:
- Router API:轻量级路由,适合简单跳转
- Navigation 组件:功能强大的声明式导航,支持路由栈管理、深层链接等
本文将从基础到进阶,全面覆盖“徒步迹“App 中的页面路由实现。
二、Router API 基础
Router 是系统提供的轻量路由 API,适合页面数不多、路由结构简单的场景。
2.1 引入模块
import { router } from '@kit.ArkUI';
2.2 基本跳转
// 1. pushUrl - 推入新页面(可返回)
router.pushUrl({
url: 'pages/RouteDetailPage',
params: { // 传递参数
routeId: 123,
routeName: '香山徒步',
},
});
// 2. replaceUrl - 替换当前页面(不可返回)
router.replaceUrl({
url: 'pages/LoginPage',
});
// 3. 返回上一页
router.back();
// 4. 返回指定页面
router.back({
url: 'pages/HomePage',
});
2.3 接收参数
// 在目标页面中接收参数
@Entry
@Component
struct RouteDetailPage {
@State routeId: number = 0;
@State routeName: string = '';
aboutToAppear(): void {
// 通过 router.getParams() 获取参数
const params = router.getParams() as Record<string, Object>;
if (params) {
this.routeId = params['routeId'] as number;
this.routeName = params['routeName'] as string;
}
}
}
三、Navigation 组件
Navigation 是鸿蒙 NEXT 推荐的声明式导航方案,功能更强大:
3.1 基本结构
Navigation() {
// 导航内容区域
Column() {
Text('首页内容')
}
}
.title('徒步迹')
.mode(NavigationMode.Auto); // 自动适配单栏/双栏模式
3.2 NavPathStack 路由栈
NavPathStack 是 Navigation 的核心路由管理工具:
@Entry
@Component
struct MainPage {
// 创建路由栈
private navStack: NavPathStack = new NavPathStack();
build() {
Navigation(this.navStack) {
Column() {
Button('查看路线详情')
.onClick(() => {
// 推入新页面
this.navStack.pushPath({
name: 'RouteDetailPage', // 路由名称
param: { // 参数
routeId: 1,
routeName: '香山徒步',
},
});
});
Button('记录轨迹')
.onClick(() => {
this.navStack.pushPathByName('TrackingPage', null);
});
}
}
.title('徒步迹')
.navDestination(this.PageMap); // 注册页面映射
}
// 页面映射
@Builder
PageMap(name: string, param: Object) {
if (name === 'RouteDetailPage') {
RouteDetailPage({ routeId: param['routeId'] as number });
} else if (name === 'TrackingPage') {
TrackingPage();
}
}
}
3.3 路由栈操作
// 1. 推入页面
navStack.pushPath({ name: 'ProfilePage', param: { userId: 1 } });
navStack.pushPathByName('SettingsPage', null);
// 2. 替换当前页面
navStack.replacePath({ name: 'LoginPage' });
navStack.replacePathByName('RegisterPage', { phone: '13800138000' });
// 3. 返回上一页
navStack.pop(); // 返回上一页
navStack.popToName('HomePage'); // 返回到指定页面
navStack.popToIndex(0); // 返回到根页面
// 4. 清除所有路由
navStack.clear();
// 5. 获取路由栈信息
let pathInfo = navStack.getPathByName('HomePage');
let index = navStack.getIndexByName('HomePage');
let size = navStack.size(); // 路由栈大小
四、页面配置
所有需要路由跳转的页面必须在 module.json5 中配置:
// module.json5 的 pages 字段
{
"module": {
"pages": "$profile:main_pages",
// ...
}
}
// resources/base/profile/main_pages.json
{
"src": [
"pages/SplashPage",
"pages/LoginPage",
"pages/RegisterPage",
"pages/HomePage",
"pages/RouteListPage",
"pages/RouteDetailPage",
"pages/TrackingPage",
"pages/TrackHistoryPage",
"pages/HealthDataPage",
"pages/TeamListPage",
"pages/TeamDetailPage",
"pages/PhotoGalleryPage",
"pages/RoadbookListPage",
"pages/RoadbookDetailPage",
"pages/ProfilePage",
"pages/SettingsPage",
"pages/AboutPage"
]
}
五、实战:徒步迹导航结构
5.1 整体路由设计
SplashPage (启动页)
└── LoginPage (登录)
└── HomePage (首页)
├── RouteListPage → RouteDetailPage
├── TrackingPage
├── TeamListPage → TeamDetailPage
├── PhotoGalleryPage
├── RoadbookListPage → RoadbookDetailPage
├── HealthDataPage
├── TrackHistoryPage
├── ProfilePage
│ ├── SettingsPage
│ └── AboutPage
└── (通过底部Tab导航)
5.2 首页 Tab 切换实现
// HomePage.ets - 带Tab导航的首页
@Entry
@Component
struct HomePage {
@State currentTab: number = 0;
private tabs: string[] = ['首页', '路线', '记录', '团队', '我的'];
build() {
Column() {
// 内容区域
if (this.currentTab === 0) {
this.HomeContent();
}
// 底部 TabBar
Row() {
ForEach(this.tabs, (tab: string, index: number) => {
Column() {
Text(tab)
.fontSize(12)
.fontColor(
this.currentTab === index
? $r('app.color.primary_color')
: $r('app.color.text_secondary')
);
}
.layoutWeight(1)
.padding(8)
.onClick(() => {
this.currentTab = index;
// 切换到其他Tab时跳转到对应页面
if (index === 1) router.pushUrl({ url: 'pages/RouteListPage' });
else if (index === 2) router.pushUrl({ url: 'pages/TrackingPage' });
else if (index === 3) router.pushUrl({ url: 'pages/TeamListPage' });
else if (index === 4) router.pushUrl({ url: 'pages/ProfilePage' });
});
}, (tab: string) => tab);
}
.width('100%')
.height(56)
.backgroundColor(Color.White);
}
.width('100%')
.height('100%');
}
@Builder
HomeContent() {
Scroll() {
// 首页内容...
}
}
}
5.3 页面间参数传递最佳实践
// 从路线列表页跳转到详情页
// RouteListPage.ets
router.pushUrl({
url: 'pages/RouteDetailPage',
params: {
routeId: 1,
source: 'RouteListPage',
},
});
// RouteDetailPage.ets - 接收参数
aboutToAppear(): void {
const params = router.getParams() as Record<string, Object>;
if (params) {
this.routeId = params['routeId'] as number;
this.source = params['source'] as string;
}
}
六、路由动画
ArkUI 支持页面切换动画的自定义:
// 自定义转场动画
router.pushUrl({
url: 'pages/RouteDetailPage',
params: { routeId: 123 },
}, router.RouterMode.Single, (err) => {
if (!err) {
// 跳转成功
}
});
// 页面内使用 animateTo 控制动画
animateTo({ duration: 300, curve: Curve.Friction }, () => {
// 状态变化触发 UI 更新
this.isVisible = true;
});
七、常见问题
7.1 页面跳转无反应
检查 main_pages.json 中是否注册了该页面路径。
7.2 参数传递丢失
确保参数类型为 Record<string, Object>,复杂对象建议先序列化。
// 传递复杂对象前先序列化
const serialized = JSON.stringify(complexObject);
router.pushUrl({
url: 'pages/RouteDetailPage',
params: { routeData: serialized },
});
// 接收端反序列化
const data = JSON.parse(params['routeData'] as string);
7.3 跨模块路由
// 跨 HAP 模块路由
router.pushUrl({
url: '@bundle:com.hiking.feature/ets/pages/FeaturePage',
});
八、总结
本文全面介绍了鸿蒙系统的页面路由方案,从简单的 Router API 到强大的 Navigation 组件,再到“徒步迹“的完整导航结构设计。良好的路由设计是 App 架构的基础。
下一篇文章将学习资源管理与多主题适配,让“徒步迹“支持多种视觉风格。
下一篇预告:鸿蒙原生开发手记:徒步迹 - 资源管理与多主题适配
如有疑问欢迎留言交流。
更多推荐




所有评论(0)