【最新鸿蒙开发——应用导航设计】

大家好,我是小z,不知道大家在开发过程中有没有遇到模块间跳转的问题,今天给大家分享关于模块间跳转的三种方法

文章目录

    • 1. 命名路由(@ohos.router)
      • 使用步骤
    • 2. 使用navigation组件跳转。
      • 步骤
      • 缺点
    • 3. 路由管理模块
      • 1. 路由管理模块实现
      • 2. 实现中的关键点
        • 动态加载
        • 路由栈管理
      • 3. 页面跳转实现
        • 主要步骤

  • 大型应用开发中,应用会分为多个模块进行开发,单个业务模块是一个HAR或一个HSP。在该场景下,通常会有从主页面跳转到其他模块页面或一个模块跳转到另一个模块的需求。针对这些需求,有三种解决办法,推荐第三种

1. 命名路由(@ohos.router)

  • 在开发中为了跳转到共享的HAR或HSP,可以使用router.pushNameRoute来实现

使用步骤

  • 导入Router模块

    import { router } from '@kit.ArkUI';
    
  • 给想要跳转到的模块中,给@Entry修饰的自定义组件命名

    // library/src/main/ets/pages/Index.ets
    // library是子模块
    @Entry({ routeName: 'myPage' })
    @Component
    export struct MyComponent {build() {}
    }
    
  • 在进行跳转的模块或HAP中的oh-package.json5文件中配置依赖

    "dependencies": {"@ohos/library": "file:../library",...
    }
    
  • 配置成功后需要在需要进行跳转的页面中引入命名路由的页面:

    import { BusinessError } from '@kit.BasicServicesKit';
    import '@ohos/library/src/main/ets/pages/Index'; // 引入共享包中的命名路由页面@Entry
    @Component
    struct Index {build() {Text('Hello World').fontSize(50).fontWeight(FontWeight.Bold).margin({ top: 20 }).backgroundColor('#ccc').onClick(() => { // 点击跳转到其他共享包中的页面this.getUIContext().getRouter().pushNamedRoute({name: 'myPage',params: {data1: 'message',data2: {data3: [123, 456, 789]}}})})}
    }
    

2. 使用navigation组件跳转。

  • 以从应用入口模块的页面NavigationPage跳转到Login子业务模块页面LoginPage为例。

步骤

  • 在Login模块中开发自定义组件LoginPage(路由跳转目的地),并对外导出。

    @Component 
    export struct LoginPage { @Consume('pathStack') pathStack: NavPathStack; @State message: string = 'Login Page'; build() { NavDestination() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) } .width('100%') .height('100%') } .onBackPressed(() => { this.pathStack.pop(); return true; }) } 
    }
    
  • 在Login模块的入口文件Index.ets中导出自定义组件。

    export { LoginPage } from './src/main/ets/pages/loginPage';
    
  • 在入口模块的oh-package.json5文件中添加对Login模块的依赖。

    { // ... "dependencies": { "login": "file:../login" } 
    }
    
  • 入口模块LoginPage页面导入Login模块的自定义组件,并添加到Navigation组件的路由表中

    // 导入Login模块自定义组件 
    import { LoginPage } from '@ohos/login'; @Entry 
    @Component 
    struct NavigationPage { @Provide('pathStack') pathStack: NavPathStack = new NavPathStack(); @Builder pageMap(name: string) { if (name === 'loginPage') { LoginPage() } } build() { Navigation(this.pathStack) { Button('jump to login page') .onClick(() => { // NavPathInfo第二个参数为自定义参数,可用于信息传递 let pathInfo: NavPathInfo = new NavPathInfo('loginPage', new Object()); this.pathStack.pushDestination(pathInfo, true); }) } .navDestination(this.pageMap) } 
    }
    

缺点

上述方案存在以下问题:

  • 使用Navigation时,所有路由页面需要主动通过import方式逐个导入当前页面,并存入页面路由表routerMap中。
  • 主动使用import的方式需显性指定加载路径,造成开发态模块耦合严重。
  • 模块无法独立编译,且存在开发态模块间循环依赖问题。

所以推荐使用方案3,路由管理模块

3. 路由管理模块

  • 将路由功能抽取成单独的模块并以har包形式存在,命名为RouterModule。将主入口模块作为其他模块的依赖注册中心,在入口模块中使用Navigation组件并依赖其他业务模块。业务模块仅依赖RouterModule,业务模块中的路由统一委托到RouterModule中管理,实现业务模块间的解耦。
    在这里插入图片描述

1. 路由管理模块实现

  • RouterModule模块包括全局路由栈(NavPathStack)和路由表信息。路由栈和Entry.hap的Navigation绑定。路由表builderMap是Map结构,以key-vaule的形式存储了需要路由的页面组件信息,其中key是自定义的唯一路由名,value是WrappedBuilder对象,该对象包裹了路由名对应的页面组件。
    在这里插入图片描述

  • 定义路由栈和路由表

    export class RouterModule {// WrappedBuilder支持@Builder描述的组件以参数的形式进行封装存储static builderMap: Map<string, WrappedBuilder<[object]>> = new Map<string, WrappedBuilder<[object]>>();// 初始化路由栈,需要关联Navigation组件static routerMap: Map<string, NavPathStack> = new Map<string, NavPathStack>();// 通过名称获取路由栈public static getRouter(routerName: string): NavPathStack {return RouterModule.routerMap.get(routerName) as NavPathStack;}// 通过传入RouterModule跳转到指定页面组件,RouterModule中需要增加routerName字段用于获取路由栈public static async push(router: RouterModel): Promise<void> {const harName = router.builderName.split('_')[0];await import(harName).then((ns: ESObject): Promise<void> => ns.harInit(router.builderName));RouterModule.getRouter(router.routerName).pushPath({ name: router.builderName, param: router.param });}//...
    }
    
  • 路由表增加路由注册和路由获取方法,业务模块通过路由注册方法将路由的页面组件交给RouteModule管理

    //通过名称注册路由表
    public static registerBuilder(builderName: string, builder: WrappedBuilder<[object]>):void{RouterModule.builderMap.set(builderName, builder);
    }
    // 获取路由表中指定的页面组件
    public static getBuilder(builderName: string): WrappedBuilder<[object]>{const builder = RouterModule.builderMap.get(builderName);if(!builder){Logger.info('not found builder ' + buiderName);}return builder as WrappedBuilder<[object]>;
    }
    
  • 路由表增加路由跳转方法,业务har模块通过调用该方法并指定跳转信息实现模块间路由跳转。

    public static async push(router: RouterModel): Promise<void> {const harName = router.builderName.split('_')[0];await import(harName).then((ns: ESObject): Promise<void> => ns.harInit(router.builderName));RouterModule.getRouter(router.routerName).pushPath({ name: router.builderName, param: router.param });
    }//其他路由方法...
    public static async replacePath(routerName: string, builderName: string, params: object): Promise<void> {const harName = builderName.split('_')[0];await import(harName).then((ns: ESObject): Promise<void> => ns.harInit(builderName));RouterModule.getRouter(routerName).replacePathByName(builderName, params);}
    

    RouterModel如下,harInit是实现动态加载的函数,帮助模块解耦

    // 路由信息类,便于跳转时传递更多信息
    export class RouterModel {// 路由页面别名,形式为${包名}_${页面名}builderName: string = "";// 路由栈名称routerName: string = "";// 需要传入页面的参数param?: object = new Object();
    }// 创建路由信息,并放到路由栈表中
    export function buildRouterModel(routerName: string, builderName: string, param?: object) {let router: RouterModel = new RouterModel();router.builderName = builderName;router.routerName = routerName;router.param = param;RouterModule.push(router);
    }
    

2. 实现中的关键点

动态加载
实现解耦的关键是使用了动态加载的方式和自执行的函数(自执行的函数是一种在定义后立即自动执行的函数)。要跳转到哪一个模块的页面,需要在该模块的index.ets文件中定义加载时的harInit- harInit函数对模块中需要注册路由的页面组件进行加载管理,被调用时将根据不同的路径动态加载不同的页面
export function harInit(builderName: string): void {// 根据routerModule中路由表的key值动态加载要跳转的页面的相对路径switch (builderName) {case BuilderNameConstants.HARB_B1:import("./src/main/ets/components/mainpage/B1");break;case BuilderNameConstants.HARB_B2:import("./src/main/ets/components/mainpage/B2");break;default:break;}
}
路由栈管理
有些业务场景需要用到多个路由栈,所以在RouterModule中,可以使用Map,以key-value形式来实现存储多个路由栈。增加路由栈后,RouterModule中的所有方法都需要先获取到相应的路由栈,再进行方法调用。
export class RouterModule {// ...// 初始化路由栈,需要关联Navigation组件static routerMap: Map<string, NavPathStack> = new Map<string, NavPathStack>();// 通过名称注册路由栈public static createRouter(routerName: string, router: NavPathStack): void {RouterModule.routerMap.set(routerName, router);}// 通过名称获取路由栈public static getRouter(routerName: string): NavPathStack {return RouterModule.routerMap.get(routerName) as NavPathStack;}// ...
}

3. 页面跳转实现

路由管理模块实现之后,需要使用RouterModule模块实现不同模块之间的跳转(如harA到harB)

主要步骤
  • 在工程主入口模块Entry.hap中引入RouterModule模块和所有需要进行路由注册的业务har模块。

    "dependencies": {"@ohos/routermodule": "file:../RouterModule","@ohos/hara": "file:../harA","@ohos/harb": "file:../harB"
    }
    
  • 在工程主入口模块Entry.hap中配置build-profile.json5文件,在该文件中修改packages字段,将需要进行路由注册的业务har模块写入配置。

    {// ..."buildOption": {"arkOptions": {"runtimeOnly": {"sources": [],"packages": ["@ohos/hara","@ohos/harb"]}}},
    }
    
  • 在工程主入口模块的首页Navigation组件关联RouterModule模块的路由栈和路由表。

    @Entry
    @Component
    struct EntryHap {@State entryHapRouter: NavPathStack = new NavPathStack();aboutToAppear() {if (!this.entryHapRouter) {this.entryHapRouter = new NavPathStack();}RouterModule.createRouter(RouterNameConstants.ENTRY_HAP, this.entryHapRouter);};@BuilderrouterMap(builderName: string, param: object) {// Obtain the WrappedBuilder object based on the module name, create a page through the builder interface, and import the param parameter.RouterModule.getBuilder(builderName).builder(param);};build() {Navigation(this.entryHapRouter) {// ...}.title('NavIndex').navDestination(this.routerMap);}
    }
    
  • 在跳转到的页面中(harB)中,声明需要跳转的页面,并且调用registerBuilder接口将页面注册到RouterModule模块的全局路由表上。如果组件中需要使用状态变量,可以将Builder函数中的组件作为一个自定义组件。

    // harB模块的B1页面
    @Builder
    export function harBuilder(value: object) {NavDestination() {Column() {// ...}// ...}// ...
    }@Builder
    export function harBuilder(value: object) {HarBPage({value:value});
    }// 在页面首次加载时触发执行
    const builderName = BuilderNameConstants.HARB_B1;
    // 判断表中是否已存在路由信息,避免重复注册
    if (!RouterModule.getBuilder(builderName)) {// 通过系统提供的wrapBuilder接口封装@Builder装饰的方法,生成harB1页面builderlet builder: WrappedBuilder<[object]> = wrapBuilder(harBuilder);// 注册harB1页面到全局路由表RouterModule.registerBuilder(builderName, builder);
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/482166.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Wireshark常用功能使用说明

此处用于记录下本人所使用 wireshark 所可能用到的小技巧。Wireshark是一款强大的数据包分析工具&#xff0c;此处仅介绍常用功能。 Wireshark常用功能使用说明 1.相关介绍1.1.工具栏功能介绍1.1.1.时间戳/分组列表概况等设置 1.2.Windows抓包 2.wireshark过滤器规则2.1.wiresh…

【进阶篇-Day15:JAVA线程-Thread的介绍】

目录 1、进程和线程1.1 进程的介绍1.2 并行和并发1.3 线程的介绍 2、JAVA开启线程的三种方法2.1 继承Thread类&#xff1a;2.2 实现Runnable接口2.3 实现Callable接口2.4 总结&#xff1a; 3、线程相关方法3.1 获取和设置线程名字的方法3.2 线程休眠方法&#xff1a;3.3 线程优…

组播基础实验

当需要同时发给多个接受者或者接收者ip未知时使用组播 一、组播IP地址 1、组播IP地址范围 组播地址属于D类地址&#xff1a;224.0.0.0/4&#xff08;224.0.0.0-239.255.255.255&#xff09; 2、分类 &#xff08;1&#xff09;链路本地地址&#xff08;link-local&#xf…

EasyDarwin搭建直播推流服务

学习链接 easydarwin官网 - 这里看介绍 easydarwin软件下载地址 - 百度网盘 easydarwin视频 B站 文章目录 学习链接使用下载EasyDarwin压缩包&#xff0c;并解压到目录启动EasyDarwin点播直播easyplayer.jsapidocffmpeg推流rtsp & ffplay拉流 使用 下载EasyDarwin压缩包…

Java有关数组的相关问题

Java中的栈和堆的含义 栈 存储局部变量&#xff1a;栈主要用于存储方法中的局部变量&#xff0c;包括基本数据类型&#xff08;int、double、boolean等&#xff09;和对象的引用&#xff08;不包含对象本身&#xff09;。 遵循后进先出原则&#xff1a;当一个方法被调用时&…

眼部按摩仪WT2605音频蓝牙语音芯片方案 单芯片实现语音提示及控制/手机无线音频传输功能

随着科技的快速发展&#xff0c;人们的生活方式也在不断改变&#xff0c;智能化、便捷化的产品逐渐成为市场的主流。眼部按摩仪作为一种结合了现代科技与健康生活理念的产品&#xff0c;受到了广大消费者的青睐。而在众多眼部按摩仪中&#xff0c;采用WT2605音频蓝牙芯片的方案…

ESP32-S3模组上跑通ES8388(12)

接前一篇文章&#xff1a;ESP32-S3模组上跑通ES8388&#xff08;11&#xff09; 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析了es8388_init函数中的第5段代码&#xff0c;本回继续往下解析。为了便于理解和回顾&#xff0c;再次贴出es8388_init函数源码&#xff0c;在…

C#VB.NET开发整体一键国际化显示

第一章链接 第二章 窗口多国语言显示 在第一章时我们已经了解如何对内容进行多语言化下面讲解如何对窗口多语言显示 在实际开发中单个窗体内可能有很多控件,如果我们对每个控件使用Mu方法进行赋值是异常繁琐的如下 Button1.Text"显示".Mu(); 在对窗口进行多语言化SG…

Linux---对时/定时服务

文章目录 目录 文章目录 前言 一.对时服务 服务端配置 客户端配置 二.定时服务 单次定时任务 循环定时任务 前言 在当今信息化高速发展的时代&#xff0c;时间的准确性和任务的定时执行对于各种系统和服务来说至关重要。Linux操作系统&#xff0c;凭借其强大的功能和灵活的…

centos更换源文件,换源,替换源

期初怎么折腾就是不行&#xff0c;换了源也是不能使用的&#xff0c;最后发现不是换的源不行&#xff0c;而是之前的源文件不行&#xff0c;然后给所有的源文件在yum源统一放在了bak目录下&#xff0c;随后我们再去下载安装源文件。 您将yum源下载之后&#xff0c;先将您的其他…

分布式系统中的Dapper与Twitter Zipkin:链路追踪技术的实现与应用

目录 一、什么是链路追踪&#xff1f; 二、核心思想Dapper &#xff08;一&#xff09;Dapper链路追踪基本概念概要 &#xff08;二&#xff09;Trace、Span、Annotations Trace Span Annotation 案例说明 &#xff08;三&#xff09;带内数据与带外数据 带外数据 带…

【深度学习基础】一篇入门模型评估指标(分类篇)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. 模…

零拷贝相关知识点(一)

前言 大家好&#xff0c;我是程序员田螺。 零拷贝是老生常谈的问题啦&#xff0c;大厂非常喜欢问。比如Kafka为什么快&#xff0c;RocketMQ为什么快等&#xff0c;都涉及到零拷贝知识点。最近技术讨论群几个伙伴分享了阿里、虾皮的面试真题&#xff0c;也都涉及到零拷贝。因此…

React+TS+css in js 练习

今天分享的内容是动态规划的经典问题--0-1 背包问题 0-1背包问题的描述如下:给定一组物品,每种物品都有自己的重量和价值,背包的总容量是固定的。我们需要从这些物品中挑选一部分,使得背包内物品的总价值最大,同时不超过背包的总容量。 举个例子&#xff1a;假设这组物品的质量…

【人工智能基础03】机器学习(练习题)

文章目录 课本习题监督学习的例子过拟合和欠拟合常见损失函数&#xff0c;判断一个损失函数的好坏无监督分类&#xff1a;kmeans无监督分类&#xff0c;Kmeans 三分类问题变换距离函数选择不同的起始点 重点回顾1. 监督学习、半监督学习和无监督学习的定义2. 判断学习场景3. 监…

【数据结构计数排序】计数排序

非比较排序概念 非比较排序是一种排序算法&#xff0c;它不是通过比较元素大小进行排序的&#xff0c;而是基于元素的特征和属性排序。这种排序方法在特定情况下&#xff0c;可以做到比元素比较排序&#xff08;快排&#xff0c;归并&#xff09;更有效率。尤其是在处理大量数…

JavaEE-经典多线程样例

文章目录 单例模式设计模式初步引入为何存在单例模式饿汉式单例模式饿汉式缺陷以及是否线程安全懒汉式单例模式基础懒汉式缺陷以及是否线程安全懒汉式单例模式的改进完整代码(变量volatile) 阻塞队列生产者消费者模型生产者消费者模型的案例以及优点请求与响应案例解耦合 单例模…

【数据结构与算法】排序算法(上)——插入排序与选择排序

文章目录 一、常见的排序算法二、插入排序2.1、直接插入排序2.2、希尔排序( 缩小增量排序 ) 三、选择排序3.1、直接选择排序3.2、堆排序3.2.1、堆排序的代码实现 一、常见的排序算法 常见排序算法中有四大排序算法&#xff0c;第一是插入排序&#xff0c;二是选择排序&#xff…

qml项目创建的区别

在Qt框架中&#xff0c;你可以使用不同的模板来创建应用程序。你提到的这几个项目类型主要针对的是Qt的不同模块和用户界面技术。下面我将分别解释这些项目类型的区别&#xff1a; 根据你提供的信息&#xff0c;以下是每个项目模板的详细描述和适用场景&#xff1a; Qt Widgets…

【热门主题】000077 物联网智能项目:开启智能未来的钥匙

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…