装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性和参数上,可以修改它所装饰对象的行为。换句话说就是装饰器可以注入到类,方法,属性参数上来扩展类,属性,方法,参数的功能。
常见的装饰器有:类装饰器,属性装饰器,方法装饰器和参数装饰器。从写法区分的话分普通装饰器(无法传参)和装饰器工厂(可传参)。
一、类装饰器
类装饰器在类声明之前声明,类装饰器应用于类构造函数,可以用来监视,修改或者替换类定义。
无法参数的普通装饰器
//类装饰器
function BaseUrl(params:any):void {
params.prototype.baseUrl = "http://www.baidu.com";
params.prototype.getResponse = function():void{
console.log("hello world");
};
};
//通过@加上装饰器的名字的形式给类添加装饰器
@BaseUrl
class Axios {
constructor(){}
};
const Http = new Axios();
console.log(Http.baseUrl); //http://www.baidu.com
Http.getResponse(); //hello world
装饰器给类的原型添加baseUrl
参数和getResponse
方法,可以让Axios
类默认绑定上装饰器里的属性和方法。
可传参的装饰器
//类装饰器
function BaseUrl(params:string) {
return function(target:any):void{
target.prototype.baseUrl = params;
target.prototype.getResponse = function():void{
console.log("hello world");
};
};
};
//通过@加上装饰器的名字的形式给类添加装饰器
@BaseUrl("http://www.baidu.com")
class Axios {
constructor(){}
};
const Http = new Axios();
console.log(Http.baseUrl); //http://www.baidu.com
Http.getResponse(); //hello world
可重载的装饰器
可重载的装饰器可用于替换类原有的属性和方法。
//类装饰器
function BaseUrl(target:any) {
return class extends target{
apiUrl:string = "http://www.google.com";
};
};
//通过@加上装饰器的名字的形式给类添加装饰器
@BaseUrl
class Axios {
public apiUrl:string;
constructor(){
this.apiUrl = "http://www.baidu.com";
}
};
const Http = new Axios();
console.log(Http.apiUrl); //http://www.google.com
二、属性装饰器
属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
以下实现一个属性装饰器,作用就是给属性添加默认值。
//属性装饰器
function BaseUrl(params: any){
return function (target: any, attr: any){
console.log(target); // Axios: {}
console.log(attr); // apiUrl
console.log(params); // http://www.baidu.com
target[attr] = params;
};
};
class Axios {
//添加属性装饰器
@BaseUrl("http://www.baidu.com")
public apiUrl: string | undefined;
constructor() {}
getData() {
console.log(this.apiUrl);
}
};
let request = new Axios();
request.getData(); // http://www.baidu.com
三、方法装饰器
方法装饰器会被应用到方法的属性描述符上,可以用来监视,修改或替换方法定义。方法装饰器定义的时候会传入以下三个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
function BaseUrl(params:any){
return function(target:any,methodName:any,desc:any){
console.log(params); //http://www.baidu.com
console.log(target); //{constructor: ƒ, getData: ƒ}
console.log(methodName); //getData
console.log(desc); //{writable: true, enumerable: false, configurable: true, value: ƒ}
target.apiUrl = params;
}
};
class Axios {
public apiUrl: string | undefined;
constructor() {}
//添加方法装饰器
@BaseUrl("http://www.baidu.com")
getData() {
console.log(this.apiUrl); //http://www.baidu.com
}
};
let request = new Axios();
request.getData();
四、方法参数装饰器
参数装饰器表达式会在运行时当作函数调用,可以使用参数装饰器为类的原型增加一些元素数据,传入以下三个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 参数的名字。
- 参数在函数参数列表中的索引。
function logClass(params: string): any {
return function(target: any, methodName: any, paramsIndex: any) {
console.log(target); // {constructor: ƒ, getData: ƒ}
console.log(methodName); // getData
console.log(paramsIndex); // 0
console.log(params); // 50
};
}
class Http {
public name: string | undefined;
constructor() {}
getData(@logClass("don") uuid: any): void {
console.log(uuid);
}
}
const h: any = new Http();
h.getData(50);
五、装饰器执行的顺序
属性装饰器——方法装饰器——方法参数装饰器——类装饰器。
如果有多个同样的装饰器,它会从后向前执行。
网友评论