基础知识

目前官方推荐的最佳解决方案,是官方对于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官方文档

下面我们就开始搭建练习项目的路由框架

项目实践

我们的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'
}

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


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

HarmonyOS Next 入门实战 - 导航框架:HMRouter的更多相关文章

  1. 零基础入门 实战mpvue2.0多端小程序框架

    第1章 课程快速预览(必看!!!)在这一章节中,老师讲带领你快速预览课程整体.其中,涉及到为什么要做这么一门实战课程.制作一个小程序的完整流程是怎么样的,以及如何做项目的技术选型. 第2章 30 分钟 ...

  2. 手动搭建I/O网络通信框架2:Socket和ServerSocket入门实战,实现单聊

    第一章:手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊 在第一章中运用Socket和ServerSocket简单的实现了网络通信.这一章,利用BIO编程模型进行 ...

  3. Bootstrap3 入门实战

    因为公司选择了使用BootStrap3作为项目的前台展示框架,所以花了半天时间来学习Bootstrap, 如果你是第一次听说,或者说以前听说过,但没有使用过这个框架的话,希望这篇入门实战能够让你快速掌 ...

  4. Spark入门实战系列--10.分布式内存文件系统Tachyon介绍及安装部署

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Tachyon介绍 1.1 Tachyon简介 随着实时计算的需求日益增多,分布式内存计算 ...

  5. Spark入门实战系列--1.Spark及其生态圈简介

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .简介 1.1 Spark简介 年6月进入Apache成为孵化项目,8个月后成为Apache ...

  6. Spark入门实战系列--3.Spark编程模型(上)--编程模型及SparkShell实战

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Spark编程模型 1.1 术语定义 l应用程序(Application): 基于Spar ...

  7. Spark入门实战系列--4.Spark运行架构

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1. Spark运行架构 1.1 术语定义 lApplication:Spark Appli ...

  8. Spark入门实战系列--5.Hive(上)--Hive介绍及部署

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Hive介绍 1.1 Hive介绍 月开源的一个数据仓库框架,提供了类似于SQL语法的HQ ...

  9. Spark入门实战系列--6.SparkSQL(中)--深入了解SparkSQL运行计划及调优

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.1  运行环境说明 1.1.1 硬软件环境 线程,主频2.2G,10G内存 l  虚拟软 ...

  10. Spark入门实战系列--7.Spark Streaming(上)--实时流计算Spark Streaming原理介绍

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Spark Streaming简介 1.1 概述 Spark Streaming 是Spa ...

随机推荐

  1. Python 潮流周刊#69:是时候停止使用 Python 3.8了(摘要)

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...

  2. 音视频入门-2-ffmpeg-Linux下编译浅析,推流拉流快速体验

      下载ffmpeg http://ffmpeg.org/download.html 1 .2 两种方式可以下载, 皆可. 编译ffmpeg ./configure -prefix=/usr/loca ...

  3. [R18][中国語翻訳]HDKのABC370赛試(ABC370)

    A.Raise Both Hands \(\texttt{Diff }11\) #include<bits/stdc++.h> using namespace std; #define e ...

  4. 第42天:WEB攻防-PHP应用&MYSQL架构&SQL注入&跨库查询&文件读写&权限操作 - 快捷方式

    接受的参数值未进行过滤直接带入SQL查询 MYSQL注入:(目的获取当前web权限) 1.判断常见四个信息(系统,用户,数据库名,版本) 2.根据四个信息去选择方案 root用户:先测试读写,后测试获 ...

  5. .NET 跨平台工业物联网网关解决方案

    前言 随着工业4.0时代的到来,物联网技术正在以前所未有的速度改变着我们的生产和生活方式.本文给大家介绍一个基于 .NET 6 开发的跨平台工业物联网网关解决方案. 工业物联网(IIoT)成为了连接物 ...

  6. PHP面试,ES

    什么是Elasticsearch? Elasticsearch是一个开源的分布式搜索和分析引擎,用于存储.搜索和分析大量数据.它基于Lucene搜索引擎构建,可以快速地执行全文搜索.结构化查询.分析和 ...

  7. 2. react项目【前端】+C#【后端】从0到1

    前端 1. 删除默认的src下所有文件,替换如下文件目录 2. src/index.js:

  8. WTConv:小参数大感受野,基于小波变换的新型卷积 | ECCV'24

    近年来,人们尝试增加卷积神经网络(CNN)的卷积核大小,以模拟视觉Transformer(ViTs)自注意力模块的全局感受野.然而,这种方法很快就遇到了上限,并在实现全局感受野之前就达到了饱和.论文证 ...

  9. AOT漫谈专题(第五篇): 如何劫持.NET AOT编译器 进行源码级调试

    一:背景 1. 讲故事 上篇聊到了 C#程序编译成Native代码 的宏观过程,有粉丝朋友提了一个问题,能不能在 dotnet publish 发布的过程中对AOT编译器拦截进行源码级调试,这是一个好 ...

  10. FluxCD 多集群应用的设计与实现

    前言 FluxCD 是 CNCF 的孵化项目,可以让我们以 GitOps 的方式轻松地交付应用.和另一个同类的 CNCF 孵化项目 ArgoCD 不同,FluxCD 是许多 toolkit 的集合,天 ...