[HarmonyOS] 解决HMRouter路由地址无法抽取的问题

解决HMRouter路由地址无法抽取的问题

背景

最近开始学习HarmonyOS开发,搭建项目的时候采用了 HMRouter 路由框架,在项目里使用到路由跳转,官方链接在这:

https://gitee.com/hadss/hmrouter/blob/master/HMRouterLibrary/README.md

但是发现一个比较严重的问题,就是路由地址无法抽取到一起进行管理,目前只能在当前的页面文件中写死路由地址,这样在项目里如果路由地址有修改,就需要在每一个页面文件里都进行修改,非常不方便。

上述表述可以用一个鲜明的例子来举证一下:

比如我们的项目结构如下:

harmony_os(项目名)|-entry|-features(业务组件模块路径)|-home(首页模块)|-mine(我的模块)|-...(其他业务模块)|-commons(公共组件模块路径)|-lib_net(网络组件)|-router_scheme(路由地址管理组件)|-...(其他公共组件)

大致如上的结构,我们希望的目标是,能够 在 router_scheme 模块里定义了所有路由地址常量,然后对于需要注册路由的 module,都来依赖这个 router_scheme 模块,这样在 router_scheme 模块里定义的路由地址常量,就能被其他 module 引用,从而避免在每一个页面文件里都写死路由地址,方便维护。

比如 将所有的 路由地址定义的常量存放到一个类或者N个类中(可以根据不同的业务module来拆分不同的类文件存放)

export class RouterConstants {public static readonly router_name_1: string = "router_name_1_value"public static readonly router_name_2: string = "router_name_2_value"public static readonly router_name_3: string = "router_name_3_value"public static readonly DemoNetPage: string = "routerscheme://entry/DemoNetPage"public static readonly DialogPage: string = "routerscheme://entry/DialogPage"public static readonly ProgramPage: string = "routerscheme://entry/ProgramPage"
}

如下图所示,红色的是路由 module,用来存放所有的路由常量类;绿色的是需要依赖路由常量类的 module,比如 feature1entry 模块,只需要依赖 router_scheme 模块,然后就可以直接引用 router_scheme 模块里定义的路由常量了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是。。。。。理想很丰满,现实很骨感啊。。。。。。。。。官方gitee 上好多 issue都提出,如果将常量抽取到单独的 har 中,会识别不到。。。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

备用链接

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是本着 办法总比困难多 的想法,还是想到了一个折中的实现方案。。。

实现方案

我们的初始目标是希望能够将所有的路由地址常量存放到一个类或者N个类中,然后对于需要注册路由的 module,都来依赖这个 router_scheme 模块,这样在 router_scheme 模块里定义的路由地址常量,就能被其他 module 引用,从而避免在每一个页面文件里都写死路由地址,方便维护。

那么现在既然官方不支持,或者说是还没支持,那我们就要想个办法,先将所有的路由常量集中到一个类中去,这样万一后续他们支持了,迁移也很方便了~~~

如下简述实现方案,技术有限,仅供参考哈~~~

主要分这么几个步骤:

- 1.实现插件,通过插件将常量类写入到每一个需要支持路由的module中,并且统一命名
- 2.添加路由键值对映射配置表(其实就是你所有的路由名字与路由地址的映射表),便于第一步的插件识别用来生成路由类
- 3.执行插件
- 4.代码引用

1.实现 HarmonyOS plugin

通过官方文档,查找到编写插件的逻辑,实现该插件,插件的主要目的是将路由映射表插入到每一个需要支持路由的 module 中,并且统一命名,方便插件识别。

将如下的 plugin 代码,命名为 RouterNamesGeneratePlugin.ts,放在 config 文件夹下,然后在项目的根路径的 hvigorfile.ts 中引入,如下所示:

这样后续只要执行 sync 就会执行下述插件代码

源码如下:

import { FileUtil, hvigor, getNode, HvigorNode, HvigorTask, HvigorPlugin } from '@ohos/hvigor';// 实现自定义插件,sync的时候自动生成路由类
export function RouterNamesGeneratePlugin(): HvigorPlugin {// 路由表JSON文件地址let namesFilePath = "config/router_names.json5"// 路由生成规则配置文件地址let configFilePath = "config/router_config.json5"// 路由类文件名称let fileName = "RouterConstants"return {pluginId: 'RouterNamesGenerate',apply(node: HvigorNode) {// 路由数据源let routerNames = FileUtil.readJson5(namesFilePath)let routerList = routerNames['rent'] // 路由对象列表if (!routerList) {console.log(`debug_hvigorfile: routerList is null`)return}// 路由配置表let routerConfig = FileUtil.readJson5(configFilePath)let moduleNames = routerConfig['moduleNames'] // 路由对象列表if (!moduleNames) {console.log(`debug_hvigorfile: moduleNames 配置的module为空,不生成路由类 `)return}console.log(`debug_hvigorfile: 路由配置表 ↓↓↓↓↓↓↓↓↓↓↓↓`)moduleNames.forEach(element => {console.log(`debug_hvigorfile: moduleName=${element}`)})console.log(`debug_hvigorfile: 路由配置表 ↑↑↑↑↑↑↑↑↑↑↑↑`)console.log(`debug_hvigorfile: 路由表原始数据 ↓↓↓↓↓↓↓↓↓↓↓↓`)routerList.forEach(element => {console.log(`debug_hvigorfile: key=${element["key"]}, value=${element["value"]}`)})console.log(`debug_hvigorfile: 路由表原始数据 ↑↑↑↑↑↑↑↑↑↑↑↑`)// 获取所有节点const allNodes = hvigor.getAllNodes();for (let i = 0; i < allNodes.length; i++) {let nodeName = allNodes[i].getNodeName()let nodeDir = allNodes[i].getNodeDir()let getPath = nodeDir.getPath()// console.log(`debug_hvigorfile: module: nodeName=${nodeName}, getPath=${getPath}`)if (moduleNames.includes(nodeName)) {// console.log(`debug_hvigorfile: module: nodeName=${nodeName}, getPath=${getPath}  可以写入`)let newFilePath = getPath + `/src/main/ets/${fileName}.ets`// 判断是否存在FileUtil.ensureFileSync(newFilePath)let exist2 = FileUtil.exist(newFilePath)// console.log(`debug_hvigorfile: exist2: ${exist2}`)let date = new Date()let formatDate = date.toLocaleString()let tips = `// 自动生成,请勿修改 \n// 生成时间:${formatDate}`let a = `${tips} \nexport class ${fileName} {\n\t`let length = routerList.lengthfor (let j = 0; j < length; j++) {let element = routerList[j]// console.log(`debug_hvigorfile: 开始写入文件>>>>> key=${element["key"]}, value=${element["value"]}`)let key = element["key"]let value = element["value"]let prefix = (j == length - 1) ? "\n" : "\n\t"a += `public static readonly ${key}: string = "${value}"${prefix}`}a += `}`// 备注:这个 写入文件,不要使用异步写入,异步写入的话会存在先执行 HMRouter 的插件的case,就容易出问题了,需要保证在执行 HMRouter 插件之前,生成完所有的路由映射类FileUtil.writeFileSync(newFilePath, a)console.log(`debug_hvigorfile: moduleName[${nodeName}]: 写入完成`)}}// FileUtil.readFile('entry/test.txt').then(function(data) {//   console.log('readFile: ' + data);// });}}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


export default {system: appTasks,plugins: [RouterNamesGeneratePlugin()]
}// 注册Task, 用于在添加路由之后,执行此任务来重新生成路由类
// 执行: hvigorw generateRouterNames  即可重新生成新的路由类
node.registerTask({name: 'generateRouterNames',run() {// 自动执行 RouterNamesGeneratePlugin}
});

2.添加配置信息

在项目的根路径下,新建 config 目录,将上述的 RouterNamesGeneratePlugin.ts 文件放进去,然后新建下述两个 json5 文件

  • 1.router_names.json5:用于存放所有的路由映射关系,json5的格式存储,键值对存储便于记录
  • 2.router_config.json5:用于配置那些 module 需要生成路由类,格式具体参考下方

举例:

router_names.json5 文件的内容规范如下:

  • rent: 便于后续区分不同的业务线,目前只设置这一个也行
  • key: 路由的名字,也就是最终在Page文件中的路由名称
  • value: 路由的具体地址
{"rent": [{"key": "DemoNetPage","value": "routerscheme://entry/DemoNetPage"},{"key": "DialogPage","value": "routerscheme://entry/DialogPage"},{"key": "ProgramPage","value": "routerscheme://entry/ProgramPage"}]
}

router_config.json5 文件的内容规范如下:

  • moduleNames: 用于配置需要生成路由类的module名字,需要在这配置一下

比如我的例子中,是要在 feature1entry 两个 module 中生成路由类,那么就将这俩module的名字配置一下。。。

{// 配置:需要生成路由类的module名字,需要在这配置一下"moduleNames": ["entry","feature1"]
}

3.执行插件

上述第一、第二步完成之后,就可以执行插件了,执行命令如下:
在项目根路径中的命令行中执行: hvigorw generateRouterNames 即可重新生成新的路由类;或者后续每次添加新的路由映射,也可以用它来执行重新生成路由映射类。

或者直接在项目根路径的 hvigorfile.ts 中随便回车一下,触发 sync 也可以执行构建。

hvigorw generateRouterNames

插件执行完毕后,会在 entryfeature1 两个 module 中生成 RouterConstants.ets 文件,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.代码引用

完成上述三步之后,那么在模块中就可以直接引用了,比如 我定义了 router_name_3 这个路由,那么在模块中就可以这样引用了:

import { RouterConstants } from “…/RouterConstants”;
@HMRouter({ pageUrl: RouterConstants.router_name_3 })

就这么简单~~~~~~

import { HMRouter } from "@hadss/hmrouter";
import { RouterConstants } from "../RouterConstants";@HMRouter({ pageUrl: RouterConstants.router_name_3 })@Entry
@Component
export struct MainPage {@State message: string = 'Hello feature1_MainPage: ' + RouterConstants.router_name_3;build() {Row() {Column() {Text(this.message).fontSize(10).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}

至此,完结有需要的小伙伴拿走不谢~
更加希望 HMRouter 后续能够支持常量抽取~~~

感谢~~~

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

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

相关文章

转录组数据挖掘(生物技能树)(第11节)下游分析

转录组数据挖掘&#xff08;生物技能树&#xff09;&#xff08;第11节&#xff09; 文章目录 R语言复习转录组数据差异分析差异分析的输入数据操作过程示例一&#xff1a;示例二&#xff1a;示例三&#xff1a;此代码只适用于人的样本 R语言复习 #### 读取 ####dat read.deli…

李宏毅机器学习课程知识点摘要(14-18集)

线性回归&#xff0c;逻辑回归&#xff08;线性回归sigmoid&#xff09;&#xff0c;神经网络 linear regression &#xff0c; logistic regression &#xff0c; neutral network 里面的偏导的相量有几百万维&#xff0c;这就是neutral network的不同&#xff0c;他是…

WonderJourney 学习笔记

目录 原理 所有场景的参数&#xff1a; 原理 Pytorch3D&#xff1a;用于高性能的3D渲染&#xff0c;确保生成的场景具有高度的真实感和细节。GPT-4&#xff1a;通过生成场景描述&#xff0c;为每一帧提供丰富的背景故事和情感。MiDaS&#xff1a;用于深度估计&#xff0c;确…

一个vue项目如何运行在docker

将 Vue.js 应用程序通过 Docker 发布是一个非常常见的做法&#xff0c;它可以帮助你轻松地部署应用到不同的环境中。下面是一个简单的指南&#xff0c;介绍如何为 Vue.js 项目创建 Dockerfile 并进行构建和运行。 第一步&#xff1a;安装 Docker 确保你的开发机器上已经安装了…

[DL]深度学习_扩散模型正弦时间编码

1 扩散模型时间步嵌入 1.1 时间步正弦编码 在扩散模型按时间步 t 进行加噪去噪过程时&#xff0c;需要包括反映噪声水平的时间步长 t 作为噪声预测器的额外输入。但是最初与图像配套的时间步 t 是数字&#xff0c;需要将代表时间步 t 的数字编码为向量嵌入。嵌入时间向量的宽…

【超全】目标检测模型分类对比与综述:单阶段、双阶段、有无锚点、DETR、旋转框

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

Llmcad: Fast and scalable on-device large language model inference

题目&#xff1a;Llmcad: Fast and scalable on-device large language model inference 发表于2023.09 链接&#xff1a;https://arxiv.org/pdf/2309.04255 声称是第一篇speculative decoding边缘设备的论文&#xff08;不一定是绝对的第一篇&#xff09;&#xff0c;不开源…

Edge浏览器保留数据,无损降级退回老版本+禁止更新教程(适用于Chrome)

3 个月前阿虚就已经写文章告警过大家&#xff0c;Chromium 内核的浏览器将在 127 以上版本开始限制仍在使用 Manifest V2 规范的扩展&#xff1a;https://mp.weixin.qq.com/s/v1gINxg5vMh86kdOOmqc6A 像是 IDM、油猴脚本管理器、uBblock 等扩展都会受到影响&#xff0c;后续将无…

人工智能零基础入门学习笔记

学习视频&#xff1a;人工智能零基础入门教程 文章目录 1.简介2.应用3.演进4.机器学习5.深度学习6.强化学习7.图像识别8.自然语言9.Python10.Python开发环境11.机器学习算法1.多元线性回归项自实战&#xff1a;糖尿病回归预测 2.逻辑回归3.Softmax回归项目实战&#xff1a;鸢尾…

Spring Boot 3 集成 Spring Security(3)数据管理

文章目录 准备工作新建项目引入MyBatis-Plus依赖创建表结构生成基础代码 逻辑实现application.yml配置SecurityConfig 配置自定义 UserDetailsService创建测试 启动测试 在前面的文章中我们介绍了 《Spring Boot 3 集成 Spring Security&#xff08;1&#xff09;认证》和 《…

Wireshark抓取HTTPS流量技巧

一、工具准备 首先安装wireshark工具&#xff0c;官方链接&#xff1a;Wireshark Go Deep 二、环境变量配置 TLS 加密的核心是会话密钥。这些密钥由客户端和服务器协商生成&#xff0c;用于对通信流量进行对称加密。如果能通过 SSL/TLS 日志文件&#xff08;例如包含密钥的…

Redis(概念、IO模型、多路选择算法、安装和启停)

一、概念 关系型数据库是典型的行存储数据库&#xff0c;存在的问题是&#xff0c;按行存储的数据在物理层面占用的是连续存储空间&#xff0c;不适合海量数据存储。 Redis在生产中使用的最多的是用作数据缓存。 服务器先在缓存中查询数据&#xff0c;查到则返回&#xff0c;…

Cobalt Strike 4.8 用户指南-第十一节 C2扩展

11.1、概述 Beacon 的 HTTP 指标由 Malleable Command and Control &#xff08;Malleable C2&#xff09; 配置文件控制。Malleable C2 配置文件是一个简单的程序&#xff0c;它指定如何转换数据并将其存储在事务中。转换和存储数据的同一程序&#xff08;向后解释&#xff0…

哪里能找到好用的动物视频素材 优质网站推荐

想让你的短视频增添些活泼生动的动物元素&#xff1f;无论是搞笑的宠物瞬间&#xff0c;还是野外猛兽的雄姿&#xff0c;这些素材都能让视频更具吸引力。今天就为大家推荐几个超实用的动物视频素材网站&#xff0c;不论你是短视频新手还是老手&#xff0c;都能在这些网站找到心…

mysql之慢查询设置及日志分析

mysql之慢查询日志分析 1.临时开启慢查询日志2.永久开启慢查询日志 慢查询是指mysql提供的日志记录功能&#xff0c;用来记录执行时间超过设置阈值的sql语句&#xff0c;并将信息写入到日志文件中&#xff1b; 1.临时开启慢查询日志 注意&#xff1a; 1.以下命令需要连接进入到…

【快速入门 LVGL】-- 1、STM32 工程移植 LVGL

目录 一、LVGL 简述 二、复制一个STM32工程 三、下载 LVGL 四、裁剪 源文件 五、工程添加 LVGL 文件 六、注册 显示 七、注册 触摸屏 八、LVGL 心跳、任务刷新 九、开跑 LVGL 十、控件的事件添加、响应处理 十 一、几个好玩小事情 十 二、显示中文 ~~ 约定 ~~ 在…

小程序租赁系统开发的优势与应用解析

内容概要 随着科技的迅猛发展&#xff0c;小程序租赁系统应运而生&#xff0c;成为许多企业优化业务的重要工具。首先&#xff0c;它提升了用户体验。想象一下&#xff0c;用户只需轻轻一点&#xff0c;就能够浏览和租赁心仪的商品&#xff0c;这种便捷的过程使繁琐的操作大大…

LLM应用-prompt提示:RAG query重写、相似query生成 加强检索准确率

参考&#xff1a; https://zhuanlan.zhihu.com/p/719510286 1、query重写 你是一名AI助手&#xff0c;负责在RAG&#xff08;知识库&#xff09;系统中通过重构用户查询来提高检索效果。根据原始查询&#xff0c;将其重写得更具体、详细&#xff0c;以便更有可能检索到相关信…

Spring Boot 3 集成 Spring Security(2)授权

文章目录 授权配置 SecurityFilterChain基于注解的授权控制自定义权限决策 在《Spring Boot 3 集成 Spring Security&#xff08;1&#xff09;》中&#xff0c;我们简单实现了 Spring Security 的认证功能&#xff0c;通过实现用户身份验证来确保系统的安全性。Spring Securit…

C++系统教程008-运算符与表达式

1.运算符与表达式 基本数据类型知道后&#xff0c;就是操作数据。要操作数据&#xff0c;就必须使用运算符和表达式。接下来就是C运算符和表达式的相关知识点&#xff0c; 赋值运算算术运算关系运算逻辑运算逗号运算位运算移位运算sizeof运算数据类型自动转换和强制转换 1.1…