- 本文所有代码案例均基于Api12。
如果一个工程中,已经使用分模块开发,多个项目要耦合到一起,难免会遇到跨模块的方法调用。在业务层,仓库A直接调用仓库B,就构成了引用,想避免引用就需要一个中间库帮他们传递消息。
AB双方约定好消息路由,分实现、注册、调用,三步实现通信。
1、创建事件路由名和实现对象: 创建实现对象,在指定方法内实现路由方法
typescript
// 路由地址,根据需要命名
let testRouter: CustomURL.Key = new CustomURL.Key("test_path")
// 路由方法实现对象,需要继承自CustomEventRouter.Protocol
export class TestEventRouter implements CustomEventRouter.Protocol {
registerRouter(navigator: CustomEventRouter.Navigator): void {
navigator.handleEvent(testRouter, (params: Record<string, Object>) => {
// xxxxxxx
return undefined
})
}
}
2、注册: APP启动后将路由对象注册给事件路由
scss
// 不同模块下的实现对象可以分别注入
CustomEventRouter.registerModule(new TestEventRouter(), new Test1EventRouter())
CustomEventRouter.registerModule(new Test2EventRouter())
3、调用: 根据路由名调用方法并获取返回参数
javascript
// 根据实际需要接收返回值,如果没有设置返回值,可以不接收
let result: Object = CustomEventRouter.open(testRouter)
这样一个事件路由就做好了。
事件路由的核心代码:
typescript
/**
* 路由地址的声明。起到代码约束功能
*/
export namespace CustomURL {
/**
* 路由地址的数据类型,约束业务模块调用规范
*/
export class Key {
// 真实的路由地址
path: string
constructor(path: string) {
this.path = path
}
}
}
export namespace CustomEventRouter {
/**
* 调用打开路由
* @param url 路由地址
* @param paramter 参数
* @returns 路由实现方法的回调
*/
export function open(
url: CustomURL.Key,
paramter?: Object
): ESObject {
if (baseNavigator.has(url.path)) {
let objFunc: Function | undefined = baseNavigator.get(url.path)
if (objFunc) {
return objFunc(paramter)
}
}
}
/**
* 注册路由实现对象的方法,每个模块需自己实现Protocol接口,app启动后在适当的时机调用该方法实现注册,如Index.ets文件
* @param items 实现路由注册接口的对象
*/
export function registerModule(...items: Protocol[]) {
let navigator: Navigator = new Navigator()
items.forEach((item: Protocol, index: number, array: Protocol[]) => {
item.registerRouter(navigator)
})
}
/**
* 移除指定路由
* @param items 要移除的路由URL
*/
export function removeURL(...items: CustomURL.Key[]) {
items.forEach((url: CustomURL.Key, index: number, array: CustomURL.Key[]) => {
baseNavigator.delete(url.path)
})
}
/**
* 需要业务组件去实现的路由接口。用协议实现对其他模块方法的调用
*/
export interface Protocol {
/**
* 在这个方法中注册路由
* @param navigator 注册的规范对象
*/
registerRouter(navigator: Navigator): void
}
/**
* RouteNavigator是用来注册的model,对代码规范约束的功能。不对外直接暴露baseNavigator,是避免map类型被错误操作
*/
export class Navigator {
/**
* 调用这个方法实现注册单条路由
* @param key 路由地址
* @param value 实现方法,Function跟系统用法相同
*/
handleEvent(key: CustomURL.Key, value: Function) {
baseNavigator[key.path] = value
}
}
/**
* 实际存储路由和方法的对象。因为是map,不对外部文件暴露,避免错误操作
*/
const baseNavigator: Map<string, Function> = new Map()
}
- 关于本文中使用到【ESObject】的说明: 在鸿蒙当前的版本中,已经不允许直接使用any类型操作对象,检查规则会报错。官方文档给了说明,他们统计过必须使用any的代码不到1%,如果特殊场景下,也给出了替代方案:
declare type ESObject = any;
在本文中,因为需要和Function对齐传参,所以使用了替代方案声明参数。