Navigation应用导航设计
将路由功能抽取成单独的模块并以har包形式存在,命名为RouterModule。RouterModule内部对路由进行管理,对外暴露RouterModule对象供其他模块使用。由于Entry.hap是应用必备的主入口,利用该特性考虑将主入口模块作为其他业务模块的依赖注册中心,在入口模块中使用Navigation组件并依赖其他业务模块。业务模块仅依赖RouterModule,业务模块中的路由统一委托到RouterModule中管理,实现业务模块间的解耦。
模块之间的依赖关系:
entry依赖:routerHar、hara、harb 也就是全部模块;
hara和harb分别依赖routerHar模块儿就行了
在自己模块的oh-package.json5加入依赖就可以了,entry为例:
entry的oh-package.json5
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"@ohos/routerhar": "file:../routerHar",
"@ohos/hara": "file:../hara",
"@ohos/harb": "file:../harb"
}
}
routerHar模块
RouterModule模块
export class RouterModule {
// 1.定义路由表和路由栈
// WrappedBuilder支持@Builder描述的组件以参数的形式进行封装存储
static builderMap: Map<string, WrappedBuilder<[object]>> = new Map<string, WrappedBuilder<[object]>>();
// 初始化路由栈,需要关联Navigation组件
// static navPathStack: NavPathStack = new NavPathStack();
// 建立NavPathStack的路由栈表,key是路由栈名,value是对应的路由栈对象
static routerMap: Map<string, NavPathStack> = new Map<string, NavPathStack>();
// 2.增加路由注册和路由获取的方法,业务模块的通过路由注册将需要路由的页面委托给RouterModule管理
// 注册页面组件到路由表,builderName是路由名字,builder参数是包裹了页面组件的WrappedBuilder对象
public static registerBuilder(builderName: string, builder: WrappedBuilder<[object]>): void {
console.log(`oneToMore registerBuilder name ${builderName},szie ${RouterModule.builderMap.size}`)
RouterModule.builderMap.set(builderName, builder);
console.log(`oneToMore registerBuilder name, ${builderName},size ${RouterModule.builderMap.size}`)
}
// 获取路由表中指定的页面组件 获取注册中的组件
public static getBuilder(builderName: string): WrappedBuilder<[object]> {
const builder = RouterModule.builderMap.get(builderName);
if (!builder) {
console.log(`oneToMore not found build ${builderName}`)
}
console.log(`oneToMore getBuilder.name ${JSON.stringify(builder?.builder.name)}`)
return builder as WrappedBuilder<[object]>;
}
// 3.增加路由表中路由跳转的方法
// 通过传入RouterModule跳转到指定页面组件,RouterModule包含跳转需要的信息
public static async push(router: RouterModel): Promise<void> {
// 从RouterModel的builderName中获取包名harName
const harName = router.builderName.split('_')[0]; // "@ohos/xxx"
console.log(`oneToMore harName ${harName} ,routerName ${router.routerName}`)
// 动态导包,包导入成功后调用包index页面的harInit方法,动态导入需要跳转的文件。该文件首次加载时将完成页面注册到RouterModule模块的builderMap中。
await import(`${harName}`)
.then((ns: ESObject) => {
console.log(`oneToMore 走的then ${JSON.stringify(ns)} `)
// 这里返回的就是这个模块
ns.harInit(router.builderName)
})
.catch((error: BusinessError) => {
console.log(`oneToMore 导入出错了 ${JSON.stringify(error.message)}`)
})
// 通过路由名跳转,并携带路由页面所需信息param
RouterModule.getRouter(router.routerName).pushPath({ name: router.builderName, param: router.param });
}
// 通过名称注册路由栈
public static createRouter(routerName: string, router: NavPathStack): void {
console.log(`oneToMore routerName ${routerName}`)
RouterModule.routerMap.set(routerName, router);
console.log(`oneToMore routerMap size ${JSON.stringify(RouterModule.routerMap.size)}`)
}
// 通过名称获取路由栈
public static getRouter(routerName: string): NavPathStack {
console.log(`oneToMore getRouter ${JSON.stringify(RouterModule.routerMap.get(routerName))}`)
return RouterModule.routerMap.get(routerName) as NavPathStack;
}
// 通过路由栈名routerName获取对应的NavPathStack对象,并使用该对象的pop方法实现返回上个路由
public static pop(routerName: string): void {
RouterModule.getRouter(routerName).pop();
}
// Get the page stack and clear it.
public static clear(routerName: string): void {
// Find the corresponding route stack for pop.
RouterModule.getRouter(routerName).clear();
}
// Directly jump to the specified route.
public static popToName(routerName: string, builderName: string): void {
RouterModule.getRouter(routerName).popToName(builderName);
}
}
RouterModel路由信息类
// 路由信息类,便于跳转时传递更多信息
export class RouterModel {
// 路由页面别名,形式为${包名}_${页面名}
builderName: string = "";
routerName: string = "";
// 需要传入页面的参数
param?: string = "";
}
// 创建路由信息,并放到路由栈表中
export function buildRouterModel(routerName: string, builderName: string, param?: string) {
let router: RouterModel = new RouterModel();
router.builderName = builderName;
router.routerName = routerName;
router.param = param;
console.log(`oneToMore router message ${JSON.stringify(router)}`)
RouterModule.push(router);
}
RouterComponents 类
Router模块中路由表的builderMap的键。格式如下:{bundleName}_${pageName}。每个模块对于的
export class BuilderNameConstants {
static readonly ENTRY_HAP: string = 'EntryHap';
static readonly HARA_A1: string = '@ohos/hara_a1';
// static readonly HARA_A2: string = '@ohos/hara_A2';
static readonly HARB_B1: string = '@ohos/harb_B1';
// static readonly HARB_B2: string = '@ohos/harb_B2';
// static readonly HARB_B3: string = '@ohos/harb_B3';
// static readonly HARC_C1: string = '@ohos/harc_C1';
// static readonly HARC_C2: string = '@ohos/harc_C2';
}
在Index.ets中导出
export { RouterModel, buildRouterModel } from './src/main/ets/model/RouterModel'
export { BuilderNameConstants } from './src/main/ets/utils/RouterComponents'
export { RouterModule } from './src/main/ets/utils/RouterModule'
entry模块
在页面中 Index.ets
import { BuilderNameConstants, buildRouterModel, RouterModule } from '@ohos/routerhar';
import { LoginPanel } from '@hms.core.account.LoginComponent';
@Entry
@Component
struct Index {
@State pageStack: NavPathStack = new NavPathStack();
// 判断有没有NavPathStack,没有就创建
aboutToAppear() {
if (!this.pageStack) {
this.pageStack = new NavPathStack();
}
RouterModule.createRouter(BuilderNameConstants.ENTRY_HAP, this.pageStack);
};
// 自定义的路由表
@Builder
routerMap(builderName: string, param: object) {
RouterModule.getBuilder(builderName).builder(param);
};
build() {
Navigation(this.pageStack){
Button("to hara")
.width('80%')
.margin({top:20})
.onClick(() => {
buildRouterModel(BuilderNameConstants.ENTRY_HAP, BuilderNameConstants.HARA_A1, "entry");
})
Button("to harb")
.width('80%')
.margin({top:20})
.onClick(() => {
buildRouterModel(BuilderNameConstants.ENTRY_HAP, BuilderNameConstants.HARB_B1, "entry");
})
}
.navDestination(this.routerMap);
}
}
hara模块
改造hara的Index.ets
根据routerModule中路由表的key值动态加载要跳转的页面的相对路径
import { BuilderNameConstants } from '@ohos/routerhar';
export function harInit(builderName:string){
console.log(`oneTomore2 到这里了没,${builderName}`)
// 根据routerModule中路由表的key值动态加载要跳转的页面的相对路径
switch (builderName) {
case BuilderNameConstants.HARA_A1:
import("./src/main/ets/components/MainPage");
break;
default:
console.log("oneTomore2 执行的这个")
break;
}
}
MainPage.ets
要注意的是这里的页面不是真正的页面,而是全局的builder
import { BuilderNameConstants, buildRouterModel, RouterModule } from '@ohos/routerhar';
@Builder
export function harBuilder(value: object) {
NavDestination(){
Column(){
Text("我的 hara")
.fontSize(30)
Button("back")
.width('80%')
.margin({top:20})
.onClick(()=>{
RouterModule.pop(BuilderNameConstants.ENTRY_HAP)
})
Button("to B1")
.width('80%')
.margin({top:20})
.onClick(()=>{
buildRouterModel(BuilderNameConstants.ENTRY_HAP,BuilderNameConstants.HARB_B1);
})
}
.width('100%')
.height('100%')
}
}
// 在这里页面第一次加载的就注册到路由表中
const builderName = BuilderNameConstants.HARA_A1;
if (!RouterModule.getBuilder(builderName)) {
const builder: WrappedBuilder<[object]> = wrapBuilder(harBuilder);
RouterModule.registerBuilder(builderName, builder);
}
注意的问题
hara等模块的builder需要加上一个接收的参数 value:object
要在entry中的build-profile.json5中添加上每个模块的依赖,不然到时候页面跳转会找不到模块
写在最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习文档能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档
鸿蒙(HarmonyOS NEXT)5.0最新学习路线
有了路线图,怎么能没有学习文档呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V3.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
《鸿蒙进阶实战》
●ArkTS实践
●UIAbility应用
●网络案例
……