news 2026/7/13 21:51:57

HarmonyOS NEXT 最强路由管理 HMRouter 完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS NEXT 最强路由管理 HMRouter 完全指南

HMRouter 是目前鸿蒙生态中功能最完善的路由框架,它封装了系统 Navigation 的复杂细节,用注解方式让页面跳转变得简单高效。本文将带你从零开始,全面掌握 HMRouter 的配置、跳转、拦截、生命周期等核心能力。


一、为什么是 HMRouter?

在 HarmonyOS 中,官方提供了两种路由方案:RouterNavigation。Router 是早期的页面路由方案,存在 32 条页面栈上限、不支持路由拦截等限制,官方已不再推荐使用 。Navigation 是当前官方主推的组件化导航方案,功能更强大,但在实际开发中仍有一些痛点:

  • 每个页面都需要手动包裹NavDestination,增加代码层级

  • 缺少统一的路由拦截机制

  • 页面生命周期管理需要自行实现

  • 跨模块跳转配置繁琐

HMRouter正是为解决这些问题而生。它在底层封装了 Navigation 的系统能力,提供了一套基于注解的声明式路由方案,让开发者几乎无需关心 Navigation 的复杂细节 。

HMRouter 核心能力一览

能力说明
📍 注解驱动@HMRouter声明页面路径,@HMInterceptor定义拦截器
🔀 跨模块跳转完美支持 HAR/HSP 之间的页面跳转
🚦 路由拦截支持全局/局部拦截器,可实现登录校验、权限控制
🔄 页面生命周期自定义生命周期处理器,监听页面事件
✨ 自定义转场动画支持页面级和全局转场动画配置
📦 单例页面通过singleton: true实现页面复用
🪟 Dialog 页面将页面以弹窗形式展示
📤 返回传参支持页面返回时携带参数

二、快速上手:从零配置 HMRouter

2.1 安装依赖

首先安装 HMRouter 核心库:

bash

ohpm install @hadss/hmrouter

如果需要使用自定义转场动画,还需安装过渡动画库:

bash

ohpm install @hadss/hmrouter-transitions

2.2 配置编译插件

修改工程根目录的hvigor/hvigor-config.json,添加路由编译插件依赖 :

json

{ "dependencies": { "@hadss/hmrouter-plugin": "^1.0.0-rc.10" } }

然后在使用 HMRouter 的模块(entry/har/hsp)的hvigorfile.ts中引入插件:

entry 模块(Hap)

typescript

// entry/hvigorfile.ts import { hapTasks } from "@ohos/hvigor-ohos-plugin"; import { hapPlugin } from "@hadss/hmrouter-plugin"; export default { system: hapTasks, plugins: [hapPlugin()] };

Har 模块:使用harPlugin()
Hsp 模块:使用hspPlugin()

2.3 工程配置

build-profile.json5中配置useNormalizedOHMUrltrue,使框架能动态导入模块 :

json

{ "buildOption": { "useNormalizedOHMUrl": true } }

2.4 初始化路由框架

EntryAbilityonCreate中初始化HMRouterMgr

typescript

// entry/src/main/ets/entryability/EntryAbility.ets import { HMRouterMgr } from '@hadss/hmrouter'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { HMRouterMgr.init({ context: this.context }); } }

2.5 定义路由入口

在首页中使用HMNavigation作为路由容器 :

typescript

// entry/src/main/ets/pages/Index.ets import { HMDefaultGlobalAnimator, HMNavigation, HMRouterMgr } from '@hadss/hmrouter'; import { AttributeUpdater } from '@kit.ArkUI'; class NavModifier extends AttributeUpdater<NavigationAttribute> { initializeModifier(instance: NavigationAttribute): void { instance.mode(NavigationMode.Stack); instance.hideTitleBar(true); instance.hideToolBar(true); } } @Entry @Component export struct Index { modifier: NavModifier = new NavModifier(); build() { Column() { HMNavigation({ navigationId: 'mainNavigation', options: { standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR, dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR, modifier: this.modifier } }) { // 首页内容 Button('跳转到登录页') .onClick(() => { HMRouterMgr.push({ pageUrl: 'LoginPage' }); }) } } .height('100%') .width('100%') } }

2.6 创建第一个页面

使用@HMRouter注解声明页面 :

typescript

// entry/src/main/ets/views/LoginPage.ets import { HMRouter } from '@hadss/hmrouter'; @HMRouter({ pageUrl: 'LoginPage' }) @Component export struct LoginPage { build() { Column() { Text('登录页面') Button('返回') .onClick(() => { HMRouterMgr.pop(); }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } }

注意事项

  • @HMRouter装饰的组件必须使用export导出

  • 默认页面目录为src/main/ets/components,可通过hmrouter_config.jsonscanDir自定义


三、页面跳转与传参

3.1 基础跳转

typescript

// push:压栈跳转,保留当前页面 HMRouterMgr.push({ pageUrl: 'ProductDetail' }); // replace:替换当前页面 HMRouterMgr.replace({ pageUrl: 'ProductDetail' }); // pop:返回上一页 HMRouterMgr.pop(); // pop 返回并携带参数 HMRouterMgr.pop({ param: { success: true } });

3.2 跳转传参

发送方

typescript

HMRouterMgr.push({ pageUrl: 'ProductDetail', param: { productId: '12345', title: '华为Mate 60' } });

接收方

typescript

@HMRouter({ pageUrl: 'ProductDetail' }) @Component export struct ProductDetail { @State productId: string = ''; @State title: string = ''; aboutToAppear(): void { const param = HMRouterMgr.getCurrentParam(); if (param) { this.productId = param.productId; this.title = param.title; } } }

3.3 页面返回结果回调

跳转时注册onResult回调,接收返回页面的数据 :

typescript

HMRouterMgr.push({ pageUrl: 'EditProfile', param: { userId: '123' } }, { onResult: (popInfo: HMPopInfo) => { const fromPage = popInfo.srcPageInfo.name; const result = popInfo.result; console.log(`从 ${fromPage} 返回,数据:${JSON.stringify(result)}`); // 处理返回数据,如刷新页面 } });

返回页发送数据

typescript

// 在 EditProfile 页面中 HMRouterMgr.pop({ param: { updated: true, newName: '张三' } });

3.4 返回指定页面

在复杂跳转链路中(如 A → B → C → D),可直接返回到指定页面并传参 :

typescript

// 从 D 页面直接返回到 A 页面 HMRouterMgr.pop({ navigationId: 'mainNavigation', pageUrl: 'HomePage', // 目标页面路径 param: { from: 'DetailPage', action: 'back' } });

3.5 跨模块跳转

HMRouter 完美支持 HAR/HSP 模块间的跳转。假设cart模块需要跳转到entry模块的页面 :

1. 在 cart 模块的hvigorfile.ts中配置编译插件

typescript

// cart/hvigorfile.ts import { hspTasks } from "@ohos/hvigor-ohos-plugin"; import { hspPlugin } from "@hadss/hmrouter-plugin"; export default { system: hspTasks, plugins: [hspPlugin()] };

2. entry 模块依赖 cart 模块

json

// entry/oh-package.json5 { "dependencies": { "cart": "file:../cart" } }

3. 在 cart 模块中定义页面

typescript

// cart/src/main/ets/views/CartDetail.ets @HMRouter({ pageUrl: 'CartDetail' }) @Component export struct CartDetail { // ... }

4. entry 模块跳转

typescript

HMRouterMgr.push({ pageUrl: 'CartDetail' });

四、路由拦截器:登录校验与权限控制

拦截器是 HMRouter 最强大的功能之一,可在跳转前执行业务逻辑,常用于登录校验、权限验证、埋点统计等场景 。

4.1 定义拦截器

实现IHMInterceptor接口,使用@HMInterceptor注解 :

typescript

import { HMInterceptor, IHMInterceptor, HMInterceptorAction, HMInterceptorInfo } from '@hadss/hmrouter'; @HMInterceptor({ interceptorName: 'LoginCheckInterceptor' }) export class LoginCheckInterceptor implements IHMInterceptor { handle(info: HMInterceptorInfo): HMInterceptorAction { // 检查登录状态 const isLogin = AppStorage.get<boolean>('isLogin') ?? false; if (isLogin) { // 已登录:继续跳转 return HMInterceptorAction.DO_NEXT; } else { // 未登录:提示并跳转到登录页 info.context.getPromptAction().showToast({ message: '请先登录' }); HMRouterMgr.push({ pageUrl: 'LoginPage', skipAllInterceptor: true // 登录页跳过拦截,防止死循环 }); // 拒绝原始跳转 return HMInterceptorAction.DO_REJECT; } } }

4.2 使用拦截器

局部拦截器(仅对指定页面生效):

typescript

@HMRouter({ pageUrl: 'ShoppingCart', interceptors: ['LoginCheckInterceptor'] // 数组形式,支持多个 }) @Component export struct ShoppingCart { // ... }

全局拦截器(对所有跳转生效):

typescript

@HMInterceptor({ interceptorName: 'GlobalLoggerInterceptor', global: true, // 全局拦截器 priority: 10 // 优先级,数字越大越先执行 }) export class GlobalLoggerInterceptor implements IHMInterceptor { handle(info: HMInterceptorInfo): HMInterceptorAction { console.log(`[路由] 从 ${info.srcPage} 跳转到 ${info.targetName}`); return HMInterceptorAction.DO_NEXT; } }

4.3 拦截器执行顺序

  1. priority降序执行(数字越大越优先)

  2. 同一优先级下,执行顺序为:发起页面拦截器 → 目标页面拦截器 → 全局拦截器


五、页面生命周期管理

HMRouter 提供了比系统更丰富的生命周期回调,通过@HMLifecycle注解定义生命周期处理器 。

5.1 定义生命周期

typescript

import { HMLifecycle, IHMLifecycle, HMLifecycleContext } from '@hadss/hmrouter'; @HMLifecycle({ lifecycleName: 'PageLifecycle' }) export class PageLifecycle implements IHMLifecycle { // 页面显示时触发 onShown(ctx: HMLifecycleContext): void { console.log('页面显示'); } // 页面隐藏时触发 onHidden(ctx: HMLifecycleContext): void { console.log('页面隐藏'); } // 返回键按下时触发(返回 true 表示拦截,false 表示执行默认返回) onBackPressed(ctx: HMLifecycleContext): boolean { console.log('用户按下返回键'); return false; // 执行默认返回 } // 页面即将出现 onWillAppear(ctx: HMLifecycleContext): void { console.log('页面即将出现'); } // 页面即将消失 onWillDisappear(ctx: HMLifecycleContext): void { console.log('页面即将消失'); } }

5.2 绑定生命周期

typescript

@HMRouter({ pageUrl: 'HomePage', lifecycle: 'PageLifecycle' // 关联生命周期处理器 }) @Component export struct HomePage { // ... }

5.3 典型场景:两次返回退出应用

typescript

@HMLifecycle({ lifecycleName: 'ExitAppLifecycle' }) export class ExitAppLifecycle implements IHMLifecycle { private lastTime: number = 0; onBackPressed(ctx: HMLifecycleContext): boolean { const now = new Date().getTime(); if (now - this.lastTime > 1000) { this.lastTime = now; ctx.uiContext.getPromptAction().showToast({ message: '再次返回退出应用' }); return true; // 拦截本次返回 } return false; // 执行返回,退出应用 } }

在首页绑定该生命周期即可实现"双击返回退出"功能 。


六、自定义转场动画

6.1 定义页面动画

使用@HMAnimator注解定义动画类 :

typescript

import { HMAnimator, IHMAnimator, HMAnimatorHandle } from '@hadss/hmrouter'; @HMAnimator({ animatorName: 'SlideUpAnimator' }) export class SlideUpAnimator implements IHMAnimator { effect(enterHandle: HMAnimatorHandle, exitHandle: HMAnimatorHandle): void { // 入场动画:从底部滑入 enterHandle.start((translate: any) => { translate.y('100%').y(0); }, { duration: 300 }); // 出场动画:滑到底部 exitHandle.start((translate: any) => { translate.y(0).y('100%'); }, { duration: 300 }); } }

6.2 使用动画

在目标页面的@HMRouter中指定动画 :

typescript

@HMRouter({ pageUrl: 'DetailPage', animator: 'SlideUpAnimator' // 使用自定义动画 }) @Component export struct DetailPage { // ... }

6.3 全局默认动画

HMNavigationoptions中配置全局动画 :

typescript

HMNavigation({ navigationId: 'mainNavigation', options: { standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR, dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR, // ... } })

七、高级特性

7.1 单例页面

当页面初始化开销较大且需要频繁复用时(如视频播放页),可配置为单例模式 :

typescript

@HMRouter({ pageUrl: 'LivePlayer', singleton: true // 页面栈中只有一个实例 }) @Component export struct LivePlayer { // ... }

7.2 Dialog 页面

将页面以弹窗形式展示 :

typescript

@HMRouter({ pageUrl: 'PrivacyDialog', dialog: true }) @Component export struct PrivacyDialog { build() { Stack({ alignContent: Alignment.Center }) { Column() { Text('隐私协议弹窗') // ... } .backgroundColor(Color.White) .borderRadius(16) .padding(20) } .width('100%') .height('100%') .backgroundColor('rgba(0,0,0,0.5)') } }

7.3 指定页面扫描目录

默认扫描src/main/ets/components,可通过配置文件自定义 :

在项目根目录创建hmrouter_config.json

json

{ "scanDir": ["src/main/ets/views", "src/main/ets/pages"] }

八、最佳实践与常见问题

8.1 最佳实践

  1. 统一管理页面路径常量

typescript

// constants/PageConstants.ets export class PageConstants { static readonly HOME = 'HomePage'; static readonly LOGIN = 'LoginPage'; static readonly PRODUCT_DETAIL = 'ProductDetail'; }
  1. 合理使用拦截器层级:全局拦截器处理通用逻辑(埋点、日志),局部拦截器处理页面特定逻辑(表单校验)。

  2. 避免拦截器死循环:在拦截器跳转登录页时,务必设置skipAllInterceptor: true

  3. 模块化开发:每个独立功能模块(HSP/HAR)独立配置编译插件,实现模块间解耦 。

8.2 常见问题

Q:跳转时提示页面未找到?
A:检查@HMRouterpageUrl是否与跳转时一致,确认页面在扫描目录下(默认components),或配置scanDir

Q:HAR 模块中的页面无法跳转?
A:确保 HAR 模块的hvigorfile.ts中配置了harPlugin(),并在宿主模块的oh-package.json5中依赖该 HAR 。

Q:如何调试路由跳转?
A:可配合系统NavPathStackgetAllPathName()方法查看当前页面栈。


九、参考资源

  • HMRouter Gitee 仓库

  • 官方示例代码

  • 接口文档

  • FAQ 常见问题

  • HMRouter 原理介绍


HMRouter 通过注解驱动和插件化编译的方式,极大地简化了 HarmonyOS 应用的路由管理。无论是基础的页面跳转、跨模块通信,还是复杂的拦截器、生命周期管理,HMRouter 都能提供优雅的解决方案。建议在新项目中直接采用 HMRouter,可以显著提升路由相关的开发效率。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 21:51:12

3步解锁Wand专业版:开源增强工具让你的游戏修改体验更智能

3步解锁Wand专业版&#xff1a;开源增强工具让你的游戏修改体验更智能 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 还在为游戏修改工具Wand&…

作者头像 李华
网站建设 2026/7/13 21:50:39

终极指南:Spatie URL包与其他PHP URL处理库的完整对比分析

终极指南&#xff1a;Spatie URL包与其他PHP URL处理库的完整对比分析 【免费下载链接】url Parse, build and manipulate URLs 项目地址: https://gitcode.com/gh_mirrors/ur/url 在PHP开发中&#xff0c;URL处理是一个看似简单却充满陷阱的任务。Spatie URL包作为一个…

作者头像 李华
网站建设 2026/7/13 21:50:01

终极wechat-jssdk入门教程:从安装到配置的完整步骤

终极wechat-jssdk入门教程&#xff1a;从安装到配置的完整步骤 【免费下载链接】wechat-jssdk &#x1f427;微信JSSDK与NodeJS及Web端集成 WeChat JSSDK integration with NodeJS & Web 项目地址: https://gitcode.com/gh_mirrors/we/wechat-jssdk 微信JSSDK是开发…

作者头像 李华
网站建设 2026/7/13 21:48:46

中国香港中文大学等多机构联合打造的智能体自动进化训练场

这项由香港中文大学、中国科学技术大学、澳门大学、清华大学、浙江大学、苏州大学、布朗大学、上海交通大学等多家机构联合完成的研究&#xff0c;于2026年7月2日以预印本形式发布在arXiv平台&#xff0c;论文编号为arXiv:2607.02440。研究的核心成果是一个名为EvoPolicyGym的评…

作者头像 李华
网站建设 2026/7/13 21:47:20

华为OD机试真题 - 软件依赖树(Java /Py/C++/Go/C/Js)

软件依赖树 华为OD机试新系统真题 华为OD上机考试新系统真题 7月12号 200分题型 华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解 题目内容 在软件项目开发里涉及不同版本组件引用,组件依赖组件,形成一棵依赖树(从根节点深层展…

作者头像 李华