HarmonyOS路由导航方案演进:HMRouter基于Navigation封装,使用更方便
HMRouter路由框架演进与使用 摘要:HMRouter是OpenHarmony三方库中基于Navigation封装的路由框架,解决了Navigation使用不便的问题并增强功能。从HarmonyOS 5.0开始,官方推荐使用HMRouter替代router和Navigation。HMRouter通过Navigation组件结构实现页面导航,包含导航页和子页管理。安装配置简单,支持自定义注解和构
HMRouter 路由框架
路由框架的演进
随着HarmonyOS的不断演进,应用路由框架也在随之更新,从最初的router到Navigation,再到现在的HMRouter,路由框架的使用体验越来越方便、能力更强。

- 从HarmonyOS 5.0开始,官方就不再推荐使用router进行路由导航了,进而推荐的是Navigation作为导航组件使用。
- HMRouter是OpenHarmony三方库中提供的路由框架,基于Navigation封装而来,解决了Navigation使用不便的问题,同时对其功能进行了增强。
Navigation 组件结构
Navigation是路由容器组件,一般作为首页的根容器。Navigation组件主要包含导航页(NavBar)和子页(NavDestination)。导航页由标题栏(Titlebar,包含菜单栏menu)、内容区(Navigation子组件)和工具栏(Toolbar)组成,其中导航页可以通过hideNavBar属性进行隐藏。
导航页与子页以及子页之间可以通过路由栈操作进行切换,导航页不在路由栈( NavPathStack )中。

HMRouter 安装
在工程目录下输入下面命令,完成HMRouter包的安装。
- 安装核心库
ohpm install @hadss/hmrouter
- 安装高级转场动画库
ohpm install @hadss/hmrouter-transitions
- 安装完成后,会在oh-package.json5文件中,添加依赖项,如下所示:

HMRouter 构建插件配置
由于HMRouter用到一些自定义注解(如@HMRouter等),默认的构建插件并不能识别这些注解。所以HMRouter提供了自定义构建插件,只需要简单配置即可。
- 修改工程根目录下的 hvigor/hvigor-config.json 文件,加入路由编译插件。
"dependencies": {
"@hadss/hmrouter-plugin": "^1.2.0-beta.0" // 使用npm仓版本号
}
- 修改工程根目录下的 hvigorfile.ts,使用路由编译插件。
import { appTasks } from '@ohos/hvigor-ohos-plugin';
import { appPlugin } from "@hadss/hmrouter-plugin";
export default {
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [appPlugin({ ignoreModuleNames: [ /** 不需要扫描的模块 **/ ] })]
}
HMRouter 初始化
在 EntryAbility中初始化路由框架,目的是让HMRouter持有UIAbility的上下文对象。
// 日志开启需在init之前调用,否则会丢失初始化日志
HMRouterMgr.openLog("INFO")
HMRouterMgr.init({
context: this.context
})
HMRouter 定义入口页面
在使用HMRouter时,一般会直接隐藏导航页,将第一个子页作为入口页面(首页),这样所有的页面都可以交给路由栈管理。
import { HMDefaultGlobalAnimator, HMNavigation } from "@hadss/hmrouter";
import { AttributeUpdater } from "@kit.ArkUI";
@Entry
@Component
export struct Index {
//Navigation的样式
modifier: MyNavModifier = new MyNavModifier();
build() {
Column() {
HMNavigation({
//配置navigationId和入口页面(首页)
navigationId: 'MainNavigation', homePageUrl: "HomePage",
options: {
standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR,
dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR,
modifier: this.modifier
}
})
}
.height('100%')
.width('100%')
}
}
class MyNavModifier extends AttributeUpdater<NavigationAttribute> {
initializeModifier(instance: NavigationAttribute): void {
instance
.hideNavBar(true) //隐藏导航页
}
}
使用HMRouter配置子页面不需要直接使用NavDestination,而是使用@HMRouter装饰@Component即可。代码人如下,将HomePage组件配置为子页。
@HMRouter({ pageUrl: 'HomePage' })
@Component
export struct HomePage {
build() {
Column() {
Text("首页").fontSize(30)
}
.width("100%")
.height("100%")
}
}
HMRouter 页面跳转与返回
如果需要切换到其他子页,只需要使用HMRouterMgr进行切换就可以了。HMRouterMgr封装了路由栈的功能。
需求:从HomePage切换到PageA,再从PageA切换到PageB,最后从PageB返回HomePage。
//HomePage.ets
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@HMRouter({ pageUrl: 'HomePage' })
@Component
export struct HomePage {
build() {
Column() {
Text("首页").fontSize(30)
Button("跳转到PageA")
.onClick(() => {
HMRouterMgr.push({pageUrl:"PageA"})
})
}
.width("100%")
.height("100%")
}
}
//PageA.ets
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@HMRouter({ pageUrl: "PageA" })
@Component
export struct PageA {
build() {
Column() {
Text("我是PageA")
Button("跳转到PageB")
.onClick(()=>{
HMRouterMgr.push({pageUrl:"PageB"})
})
}.width("100%")
.height("100%")
}
}
//PageB.ets
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@HMRouter({ pageUrl: "PageB" })
@Component
export struct PageB {
build() {
Column() {
Text("PageB").fontSize(30)
Button("返回到首页")
.onClick(() => {
HMRouterMgr.pop({ pageUrl: "HomePage" })
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
HMRouter 路由传参
HMRouter的路由传参分为URL参数和实体参数。
示例1:我们想要从PageA页面切换到PageB页面,同时传递url参数**"username=lisi&password=123"**给PageB页面。
- 在PageA中使用HMRouterMgr.push(“PageB?username=lisi&password=123”)切换到目标页面同时携带参数。代码如下
//PageA.ets
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@HMRouter({ pageUrl: "PageA" })
@Component
export struct PageA {
build() {
Column() {
Text("我是PageA")
Button("跳转到PageB")
.onClick(()=>{
HMRouterMgr.push({pageUrl:"PageB?username=lisi&password=123"})
})
}.width("100%")
.height("100%")
}
}
- 在PageB页面中使用HMRouterMgr.getCurrentParam(HMParamType.urlParam)获取url参数,需要注意的是返回值为Map<string, Object>类型。
//PageB.ets
import { HMParamType, HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@HMRouter({ pageUrl: "PageB" })
@Component
export struct PageB {
@State username: string | undefined = undefined
@State password: string | undefined = undefined
aboutToAppear(): void {
const params = HMRouterMgr.getCurrentParam(HMParamType.urlParam) as Map<string, Object>
this.username = params.get("username") as string
this.password = params.get("password") as string
}
build() {
Column() {
Text("PageB").fontSize(30)
Text(this.username+":"+this.password).fontSize(20)
Button("返回到首页")
.onClick(() => {
HMRouterMgr.pop({ pageUrl: "HomePage" })
})
}
.width("100%")
.height("100%")
}
}
示例1:我们想要从PageA页面切换到PageB页面,同时传递实体参数**new User("zhangsan“,"123")**给PageB页面。
- 在PageA页面中使用HMRouterMgr.push({pageUrl:“PageB”,param:new User(“zhangsan”,“123”)}) 跳转页面并传递参数。
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"
class User{
username:string
password:string
constructor(username: string, password: string) {
this.username = username
this.password = password
}
}
@HMRouter({ pageUrl: "PageA" })
@Component
export struct PageA {
build() {
Column() {
Text("我是PageA")
Button("跳转到PageB")
.onClick(()=>{
HMRouterMgr.push({pageUrl:"PageB",param:new User("zhangsan","123")})
})
}.width("100%")
.height("100%")
}
}
- 在PageB页面中使用HMRouterMgr.getCurrentParam(HMParamType.routeParam) as User 获取实体参数。
@HMRouter({ pageUrl: "PageB" })
@Component
export struct PageB {
@State username: string | undefined = undefined
@State password: string | undefined = undefined
aboutToAppear(): void {
const user:User = HMRouterMgr.getCurrentParam(HMParamType.routeParam) as User
this.username = user.username
this.password = user.password
}
build() {
Column() {
Text("PageB").fontSize(30)
Text(this.username+":"+this.password).fontSize(20)
Button("返回到首页")
.onClick(() => {
HMRouterMgr.pop({ pageUrl: "HomePage" })
})
}
.width("100%")
.height("100%")
}
}
HMRouter 返回传参
页面跳转完成后再返回到原页面时,携带参数到原页面。此时使用HMRouterMgr.push()中添加onResult()回调处理返回的数据。
示例:从PageA切换到PageB再返回到PageA,再PageA中接收PageB返回时携带的参数。
- 在PageA中HMRouterMgr.push()回调中添加onResult()回调,用于处理从上一个页面返回的结果,代码如下。
//PageA.ets
import { HMPopInfo, HMRouter, HMRouterMgr } from "@hadss/hmrouter"
export class User {
username: string
password: string
constructor(username: string, password: string) {
this.username = username
this.password = password
}
}
@HMRouter({ pageUrl: "PageA" })
@Component
export struct PageA {
@State fromPageBParams: string | undefined = undefined
build() {
Column() {
Text("我是PageA")
if (this.fromPageBParams) {
Text("从PageB返回的数据:" + this.fromPageBParams)
}
Button("跳转到PageB")
.onClick(() => {
HMRouterMgr.push(
{ pageUrl: "PageB", param: new User("zhangsan", "123") },
{
onResult: (popInfo: HMPopInfo) => {
const user = popInfo.result as User
this.fromPageBParams = user.username+":"+user.password
}
}
)
})
}.width("100%")
.height("100%")
}
}
- 在PageB中HMRouterMgr.pop()回调中添加param参数,代码如下。
import { HMParamType, HMRouter, HMRouterMgr } from "@hadss/hmrouter"
import { User } from "./PageA"
@HMRouter({ pageUrl: "PageB" })
@Component
export struct PageB {
@State username: string | undefined = undefined
@State password: string | undefined = undefined
aboutToAppear(): void {
const user:User = HMRouterMgr.getCurrentParam(HMParamType.routeParam) as User
this.username = user.username
this.password = user.password
}
build() {
Column() {
Text("PageB").fontSize(30)
Text(this.username+":"+this.password).fontSize(20)
Button("返回PageA")
.onClick(() => {
HMRouterMgr.pop({ pageUrl: "PageA",param:new User("小明","666")})
})
}
.width("100%")
.height("100%")
}
}
HMRouter页面绑定生命周期
IHMLifecycle是HMRouter框架中的页面生命周期接口,定义了页面在不同状态下的回调方法,这些回调方法的触发时机与NavDestination生命周期函数保持一致。

给页面绑定生命周期

对鸿蒙感兴趣的同学,可以考免费取鸿蒙开发者认证
更多推荐



所有评论(0)