目录
- 一、装饰器的作用
- 二、类装饰器
- 1. 普通装饰器
- 为类扩展属性和方法
- 使用装饰器修改属性和重写方法
- 2. 装饰器工厂
- 1. 普通装饰器
- 三、属性装饰器
- 四、方法装饰器
- 使用方法装饰器对方法进行扩展
- 五、方法参数装饰器
- 六、装饰器的执行顺序
一、装饰器的作用我个人的理解是:
ts中的装饰器类似于 Java 语言中的注解,对于用户来说都是为类和属性等代码元素添加额外的功能,而不改变代码元素原有的结构 。例如在 Java 中我们用的比较多的 Spring 框架中的注解 @Component 可以将一个类放置到 IoC 容器中进行托管,使用 @Autowired 来取出该对象进行使用等等 。二、类装饰器1. 普通装饰器先写一个最简单的类装饰器,它看起来就是一个方法:
function logClass(params:any) {console.log(params);}使用方式如下,非常类似Java的注解:@装饰器名class 被装饰的类 {...}然后我们编写一个类来进行装饰:@logClass // <-- 类装饰器的使用方式class HttpClient {constructor() {}getData() {}}查看运行的结果:
文章插图
可以看出,
logClass 参数 params 中得到的是修饰的类(在console中打印出类型是方法的原因是ts中的类在编译成js代码后,会变成一个函数)为类扩展属性和方法扩展属性
这里为被修饰的类添加一个
info 属性:function logClass(params:any) { // 在原型链上添加附加属性params.prototype.info = '附加信息'}然后我们将这个属性打印出来:let httpClient:any = new HttpClient();console.log(httpClient.info);运行结果:
文章插图
tips:注意这里的创建的对象的类型需要指定为
any 才可以使用 info 属性扩展方法
同理,我们也可以为被修饰的类扩展方法:
function logClass(params:any) {params.prototype.run = function() {console.log("我是扩展的run方法");}}方法调用:let httpClient:any = new HttpClient();httpClient.run();运行结果:
文章插图
使用装饰器修改属性和重写方法语法:
function 装饰器名(target:any) {return class extends target {原有的某属性:any = "我是修改后的数据";原有的某方法() {//...重写的内容}}}示例:function logClass(target:any) {return class extends target {apiUrl:any = "我是修改后的数据";getData() {this.apiUrl += "-----";console.log(this.apiUrl);}}}被修饰的类:@logClassclass HttpClient {public apiUrl: string | undefined;constructor() {}getData() {}}运行代码:let httpClient:HttpClient = new HttpClient();httpClient.getData();运行结果:
文章插图
可以看到,使用装饰器,我们不需要编写子类即可修改类的属性和重写类的方法了!
2. 装饰器工厂当我们使用普通装饰器时可以发现,我们是无法传递参数的,而现在要学的装饰器工厂则可以传递参数 。
语法格式:
function 装饰器名(参数列表) {return function(target: any) {...}}现在参数列表中的是我们输入的参数,而 target 是被装饰的类 。示例:
function logClass(params:string, p2?:string) {return function(target: any) {console.log("params",params);console.log("p2",p2);console.log("target",target);}}被装饰的类:@logClass("hello world", "第二个参数")class HttpClient {constructor() {}getData() {}}运行结果:
文章插图
三、属性装饰器定义方式:
function 属性装饰器名() {return function(target: any, attr: any) {...}}这里返回的 function 有两个参数:- 对于静态成员来说是类的
构造函数,对于实例成员来说是类的原型对象 - 成员的名字(
string类型)
属性装饰器:
function logProperty(params: any) {return function(target: any, attr: any) {target[attr] = params;}}被装饰的类:// @logClassclass HttpClient {@logProperty("hello world")public apiUrl: string | undefined;constructor() {}getData() {}}打印属性:let httpClient:HttpClient = new HttpClient();console.log(httpClient.apiUrl);运行结果:
文章插图
可以看到属性的值被修改为了我们传入到注解中的值了 。
四、方法装饰器定义方式:
function 装饰器名(参数列表) {return function(target:any, methodName:any, desc:any) {...} }这里返回的 function 有三个参数:target是修饰的类的对象原型methodName是方法名desc方法的描述信息对象
function Get(url:string) {return function(target:any, methodName:any, desc:any) {console.log(target);console.log(methodName);console.log(desc);} }【四 TypeScript学习笔记装饰器】class HttpClient {constructor() {}@Get("http://www.itying.com")getData() {}}运行结果:
文章插图
使用方法装饰器对方法进行扩展被修饰类:
class HttpClient {constructor() {}getData(...args:any[]) {console.log(args);}}此时我们希望扩展 getData() 方法的功能:在执行前后进行日志打印,并将传入的参数先转换为 string 类型 。具体的装饰器如下:
function logMethod() {return function(target:any, methodName:any, desc:any) {// 先保存原来的函数let originMethod:Function = desc.value;// 修改函数的实现desc.value = https://tazarkount.com/read/function(...args:any[]) {// 数据预处理(转为string)args = args.map(value=>String(value));// 运行前日志console.log(`====函数${methodName}运行前====`);// 调用原函数originMethod.apply(this, args);// 运行后日志console.log(`====函数${methodName}运行后====`);}} }创建对象并调用方法:let httpClient:HttpClient = new HttpClient();httpClient.getData(1,2,3);运行结果:
文章插图
五、方法参数装饰器定义方法:
function logParam(){return function(target:any, methodName:any,paramIndex:any) {...}}定义方法和方法装饰器基本一致,区别在于三个参数不同:target是修饰的类的对象原型methodName是方法名paramIndex是参数的索引
function logParam(){return function(target:any, methodName:any,paramIndex:any) {console.log(target);console.log(methodName);console.log(paramIndex);}}被修饰的类class HttpClient {// @logProperty("hello world")public apiUrl: string | undefined;constructor() {}getData(@logParam() str:string) {console.log("getData函数被调用了");}}运行结果:
文章插图
六、装饰器的执行顺序
属性装饰器 => 方法装饰器 => 方法参数装饰器 => 类装饰器
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
