HarmonyOS Next 入门实战 – 导航框架:HMRouter

基础知识

目前官方推荐的最佳解决方案,是官方对于Navigation导航组件的封装,使用更简单便捷。如果熟悉Navigation的话,使用起来很快上手。

首先先集成HMRouter模块
使用命令行安装依赖:

ohpm install @hadss/hmrouter 

或在模块的 oh-package.json5 文件中添加依赖

{   "dependencies": {     "@hadss/hmrouter": "^1.0.0-rc.6",   } } 

插件配置
在项目级的 hvigor/hvigor-config.json5 中添加插件依赖

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

在模块的 hvigorfile.ts 文件中应用插件

import { hapTasks } from '@ohos/hvigor-ohos-plugin'; import { hapPlugin } from '@hadss/hmrouter-plugin';  //导入插件  export default {     system: hapTasks,     plugins:[hapPlugin()]   //应用插件, }  //还有harPlugin(),hspPlugin(),模块是什么类型,就用对应的方法 

在项目的build-profile.json5中,配置useNormalizedOHMUrl属性为true

{   "app": {     "products": [       {         "name": "default",         "signingConfig": "debug",         "compatibleSdkVersion": "5.0.0(12)",         "runtimeOS": "HarmonyOS",         "buildOption": {           "strictMode": {             "useNormalizedOHMUrl": true           }         }       }     ],   } } 

HMRouter的配置就完成了。

初始化HMRouter

在入口的 UIAbility 类中(通常名字为EntryAbility )的 onCreate() 方法中调用HMRouter初始化方法,

export default class EntryAbility extends UIAbility {   onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {     hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');     //初始化HMRouterMgr       HMRouterMgr.init({       context: this.context     })   } } 

定义首页

HMNavigation 用来包裹首页内容:
其中 homePageUrl 为加载时显示的页面地址,options中可以设置框架的属性(NavModifier)和首页的元素,设置内容基本与Navigation相同。

class NavModifier extends AttributeUpdater<NavigationAttribute> {   initializeModifier(instance: NavigationAttribute): void {     instance.mode(NavigationMode.Stack);     instance.navBarWidth('100%');     instance.titleMode(NavigationTitleMode.Mini)     instance.hideBackButton(true)     // instance.hideNavBar(true)   } }   @Entry @Component struct HMRouterPage {   static readonly TAG = 'HMRouterPage'   modifier: NavModifier = new NavModifier()    aboutToAppear(): void {      HMRouterMgr.registerPageBuilder({       builder: wrapBuilder(PageOneBuilder),       pageUrl: "pageOne",     })   }    build() {     Column() {       HMNavigation({         homePageUrl: '',         navigationId: 'mainNavigation', options: {           // standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR,           // dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR,           modifier: this.modifier,           title: { titleValue: "首页" },           menus: [{             value: "menu1",             icon: "resources/base/media/menu1.png",             action: () => {              }           }, {             value: "menu2",             icon: "resources/base/media/menu2.png",             action: () => {              }           }]         }       }) {         PageMain()       }     }.width('100%').height('100%')   } } 

定义子页
使用@HMRouter定义子页面路由
使用HMRouterMgr的 push(),replace(),pop()等方法进行页面之间的导航
使用HMRouterMgr.getCurrentParam()获取当页面的参数

//PageA @HMRouter({ pageUrl: 'pageA' }) @Component export struct PageA {    build() {     Column() {       Text("Page A")       Button("Page B").onClick(() => {         HMRouterMgr.push({ pageUrl: 'pageB', param: "param" })       })       Button("Back").onClick(() => {         HMRouterMgr.pop({ param: "pageA backParam" })       })     }   } }  //PageB @HMRouter({ pageUrl: 'pageB'}) @Component export struct PageB {   @State params: string | undefined = HMRouterMgr.getCurrentParam()?.toString()     build() {     Column(){       Text("Page B")       Text("params:" + this.params)       Button("Page B").onClick(()=>{         HMRouterMgr.pop({ param: "pageB backParam" })       })     }   } } 

另一种方法HMRouterMgr.registerPageBuilder
使用HMRouterMgr.registerPageBuilder()动态注册子页面路由,子页面内容使用NavDestination组件包括,无缝将Navigation框架迁移到HMRouterMgr

//定义子页面builder @Builder export function PageOneBuilder() {   PageOne() }  @Component export struct PageOne {   @State params: string | undefined = HMRouterMgr.getCurrentParam()?.toString()    build() {     NavDestination() {       Column() {         Text("page1")           .padding(10)           .fontSize(20)           .fontWeight(500)       }       .width('100%')       .height('100%')       .alignItems(HorizontalAlign.Center)       .justifyContent(FlexAlign.Center)     }     .title("page1")     .menus([{       value: "menu1",       icon: "resources/base/media/menu1.png",       action: () => {        }     }, {       value: "menu2",       icon: "resources/base/media/menu2.png",       action: () => {       }     }])   } }  //动态注册路由 HMRouterMgr.registerPageBuilder({   builder: wrapBuilder(PageOneBuilder),   pageUrl: "page1", }) 

HMRouter还有拦截器,生命周期,转场动画,服务路由等功能,限于篇幅不在细说,可以查看官方文档:
HMRouter官方文档
下面我们就开始搭建练习项目的路由框架

项目实践

注意:原本项目实战中打算使用HMRouter组件,实际发现使用HMRouter时菜单icon无法动态更新,因此替换成Navigation组件。
我们的demo中涉及三个页面,首页,详情页,作者页。首页作为路由主页面,详情页及作者页作为路由子页面。因此我们只需要注册后2个页面路由即可。

首页

@Builder function PageMap(name: string) {   if (name == PageURls.PoetryDetailPage) {     PoetryDetailPage()   } else if (name == PageURls.AuthorPage) {     AuthorPage()   } }   //首页 @Entry @Component struct Index {   @Provide('navPathStack') navPathStack: NavPathStack = new NavPathStack()    build() {     Stack() {       Navigation(this.navPathStack) {         Column() {           Button(PageURls.PoetryDetailPage)             .onClick(() => {               this.navPathStack.pushPath({ name: PageURls.PoetryDetailPage })             })         }       }       .navDestination(PageMap)       .titleMode(NavigationTitleMode.Mini)       .title("首页")       .hideBackButton(true)     }.width('100%').height('100%')   } } 

详情页

//详情页 @Component export struct PoetryDetailPage {   @Consume('navPathStack') navPathStack: NavPathStack    build() {     NavDestination() {       Text("详情页")     }.title({       main: this.poetry!!.title,       sub: `[${this.poetry!!.dynasty}]${this.poetry!!.author}`     }).menus([{       value: "作者",       icon: "resources/base/media/ic_person_24px.svg",       action: () => {         this.navPathStack.pushPath({ name: PageURls.AuthorPage })       }     }])   } } 

作者页

//作者页 @Component export struct AuthorPage {     @Consume('navPathStack') navPathStack: NavPathStack    build() {     NavDestination() {       Column() {         Text("AuthorPage")       }       .alignItems(HorizontalAlign.Center)       .justifyContent(FlexAlign.Center)       .width('100%')       .height('100%')     }.title(this.name)   } } 
//PageUrl export class PageUrls{   public static PoetryDetailPage = 'PoetryDetailPage'   public static AuthorPage = 'AuthorPage' } 

到此我们基本的导航框架已经搭建完成,下一步我们来实现首页的列表展示。


本文的技术设计和实现都是基于作者工作中的经验总结,如有错误,请留言指正,谢谢。

发表评论

评论已关闭。

相关文章