TS的装饰器

TypeScript



装饰器


装饰器是一种特殊类型的声明,他能被附加到类声明,方法属性或参数上,可以修改类的行为

本质上就是一个方法,可以注入到类、方法、属性参数上来拓展类、属性、方法、参数的功能

常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器

装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)



类装饰器

类装饰器在类声明之前被声明(紧靠着类声明)

类装饰器应用于类构造函数,用来监视,修改或替换类定义

参数1:为装饰器装饰的构造函数

function logClass(params:any){
	console.log(params); // params为装饰的构造函数HttpClient
	params.prototype.apiUrl='动态拓展的属性' // 为构造函数HttpClient的原型添加属性
}

@logClass
class HttpClient{
	constructor(){
	}
	getData(){
	}
}

类的工厂装饰器

需要装饰器传参时必须在装饰器函数中return一个函数 此时返回的函数才是装饰器函数

参数1:为装饰器函数的传参

function logClass(params:string){
	return function(target:any){
		console.log(target); // target为装饰的构造函数HttpClient
		console.log(params); // params为装饰器的传参
	}	
}

@logClass('hello')
class HttpClient{
	constructor(){
	}
	getData(){
	}
}

类的重载
function logClass(target: any) {
  console.log(target); 
  return class extends target {
    apiUrl:any = '修改后的数据'
    getData(){
		console.log(this.apiUrl);
    }
  }
}

@logClass
class HttpClient {
  public apiUrl:string | undefined
  constructor() {
    this.apiUrl = '构造函数中的apiUrl'
  }
  getData() {
    console.log(this.apiUrl);
  }
}

const http = new HttpClient();
http.getData();

通过装饰器中进行类继承构造函数可以实现类的重载

修改类中的属性方法并实现(原先类中的方法会被覆盖)




属性装饰器

属性装饰器表达式会在运行时当做构造函数被调用 传入两个参数

参数1:对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
参数2: 成员的名字

function logProperty(params: any) {
  return function(target:any, attr:any) {
    console.log(target); // 构造函数
    console.log(attr);   //url --成员的命名
    target[attr] = params;    
  }
}


class HttpClient {
  @logProperty('xxx')
  public url: any | undefined;
  constructor() {
  }
  getData() {
    console.log(this.url); // 被装饰器修改后的属性 为 xxx
    
  }
}

const http = new HttpClient();
http.getData();




方法装饰器

应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义

方法装饰器在运行时传入三个参数

参数1:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
参数2:成员的名字
参数3:成员的属性描述符

function get(params: any) {
  return function(target:any, methodName:any, desc:any) {
    console.log(target);      // 构造函数
    console.log(methodName);  // 装饰器的方法名
    console.log(desc);        // 属性描述符的对象 desc.value为装饰的函数
    target.apiUrl = 'xxx';    // 为实例对象添加属性和方法
    target.run = function(){
      console.log('run');    
    } 
  }
}


class HttpClient {
  public url: any | undefined;
  constructor() {
  }
  @get('123')
  getData() {
    console.log(this.url);    
  }
}

const http = new HttpClient();
console.log(http.apiUrl);
http.run();


通过方法装饰器来拓展原方法的功能

function get(params: any) {
  return function(target:any, methodName:any, desc:any) {
    console.log(target);      
    console.log(methodName);  
    console.log(desc);        
    let oldMethod = desc.value  			 	// 将旧方法保存在oldMethod中
    desc.value = function(...argus:any[]){		// 将getData重新赋值并补充业务逻辑
      argus = argus.map((ele) => {
        return String(ele);
      })
      oldMethod.apply(this,argus)				// 调用新方法并将this绑定回实例对象
    }
  }
}


class HttpClient {
  public url: any | undefined;
  constructor() {
  }
  @get('123')
  getData(...argus:any[]) {
    console.log(argus);    						// 打印出装饰器处理过的argus
  }
}

const http = new HttpClient();
http.getData(123, 'xxx')




方法参数装饰器

参数装饰器表达式会在运行时当做函数被调用,可以使用参数装饰器为类的原型增加一些元素数据

调用时传入三个参数

参数1:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
参数2:参数的名字
参数3:参数在函数参数列表中的索引

function logParams(params: any) {
  return function(target:any, methodName:any, paramsIndex:any) {
    console.log(params);  		// 装饰器的传参
    console.log(target);      	// 装饰器的构造函数
    console.log(methodName);  	// 装饰的方法名
    console.log(paramsIndex);	// 参数的索引 为0
  }
}
class HttpClient {
  public url: any | undefined;
  constructor() {
  }
  getData(@logParams('xxx') uuid:any) {
    console.log(uuid);    		// 打印出实参123
  }
}

const http = new HttpClient();
http.getData(123)




装饰器的执行顺序


属性装饰器 > 方法装饰器 > 方法参数装饰器 > 类装饰器

如果有多个同样的装饰器,会先执行后面的

function logClass1(params:string){
	return function(target:any){
	}	
}
function logClass2(params:string){
	return function(target:any){
	}	
}

@logClass1('hello')
@logClass2('hello')        	// 先执行装饰器logClass2 再执行logClass1
class HttpClient{
	constructor(){
	}
	getData(){
	}
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raccom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值