本文已参与「新人创作礼」活动,一起开启掘金创作之路。
#题记:通过该文章你能了解什么?
- 了解到TS的
装饰器(Decorators)
是什么?以及它的简单机制。 - 如何通过
装饰器(Decorators)
实现一个模块的解耦
。
一、TypeScript
的装饰器(Decorators
)
熟悉Java
的同学对注解肯定不陌生。毕竟sprint
全家桶注解的应用是相当多。在JAVA
中注解分为编译时注解、运行时注解。 而TS
的装饰器可以理解成一种编译时注解,也就是在编译的过程中执行的,也就是在import
加入了装饰器的文件时。
装饰器
可以加在 类名、方法、参数上。 通过装饰器我们可以为(类、方法、参数)执行一些特别的定制。比如:为类加一个方法、加一个参数、比如为参数加一个 代理(proxy) ,诸如此类...装饰你想要的数据,监听它、修改它、替换它...
关于装饰器基本实用大家可以看官网之类的了解下:
(这里是一个TS中文网) typescript.bootcss.com/decorators.…
二、使用装饰器实现模块解耦小思路
下面以
导入配置生成不同的节点
这个功能为示例,我们需要的是: 首先导入配置有一个默认的生成流程,但是在该流程上可能会根据不同的配置进行一些不同的处理操作。而我们希望这些不同的配置操作能和导入相关代码完全解耦,作为一个插件使用。
1、开启tsconfig.json
中的设置,启用experimentalDecorators
编译器选项.
"compilerOptions": {
...
"experimentalDecorators": true,
...
}
2、未加入装饰器前
未加入 装饰器前
,我们有一个工厂,里面进行了节点的创建工作。假设该代码在一个依赖库中,其他的协同开发人员引入了该工厂依赖,我们将使用装饰器
为开发人员提供一些可供其自定义创建的功能。
export class NodeFactory {
async createNode(){
// 下面是创建的方法...
readConfig()
//...
createByConfig()
//...
}
}
3、定义装饰器
,提供插件方法
//构建队列数组
const NodeFactoryCreatorHooks: typeof ICreateHook[] = [];
export {
NodeFactoryCreatorHooks,
};
/**
* 构建装饰器:外部通过在class上@nodeCreatorHook使用
* 没到import插件的时候,将插件放入到数组里面
*/
export function nodeCreatorHook(target: typeof ICreateHook) {
NodeFactoryCreatorHooks.push(target);
}
/**
* 依赖注入监听
*/
export abstract class ICreateHook {
//排序:值越大越后面执行
public sort: number = 10;
//创建前拦截
abstract onCreateBefore(params): any;
//创建后拦截
abstract onCreateAfter(params): any;
}
4、工厂中使用声明了装饰器的插件
export class NodeFactory {
//获取装饰器插件数组
public creatorHooks: ICreateBlockHook[] = [];
private static _instance: NodeFactory;
private constructor() {
//加载hook对象
NodeFactoryCreatorHooks.forEach((hook:any) => {
this.creatorHooks.push(new hook());
//排序
this.creatorHooks.sort((a, b) => (b.sort > a.sort ? -1 : 0));
});
}
public static get instance(): NodeFactory {
if (!this._instance) {
this._instance = new NodeFactory();
}
return this._instance;
}
async createNode(){
// 下面是创建的方法...
const config =readConfig()
//创建前调用插件的相关监听钩子
this.creatorHooks.forEach((task) => {
task.onCreateBefore(config);
});
//...
createByConfig(config)
//...
//创建后调用插件的相关监听钩子
this.creatorHooks.forEach((task) => {
task.onCreateAfter(config);
});
}
}
以上,依赖提供插件的方式就已经实现完成了。
5、定义一个插件
//类名上使用装饰器,继承插件基础类
@nodeCreatorHook
export class LogCreatorHook extends ICreateHook {
public sort: number = 1;
//创建前拦截
public onCreateBefore(config): any{
console.log("马上要创建节点了,配置是:",config)
}
//创建后拦截
public onCreateAfter(config): any{
console.log("节点已经创建了,配置是:",config)
}
}
6、使用插件
在需要的项目中import一下即可为项目开启该插件,注意import顺序应在ICreateHook的依赖之后import
//相关Hook插件导入
import '@/hooks/cretor-hook';
7、备注:
使用过程中发现类似 umi
之类的框架import
的顺序是和编写顺序不一致,想必和改动了webpack
有关系,可以在找一个应用启动的时机(或者运行时)import
瑞思拜~ see you ~
加油加油~ 2/300