TypeScript 装饰器
开启装饰器需要在tsconfig.json
或jsconfig.json
中开启
json
"experimentalDecorators": true
类装饰器
普通装饰器(不能传参)
ts
function myDestroyed(params: any) {
console.log(params); // params 就是当前类
params.prototype.age = 123;
}
@myDestroyed
class Person {
public name: string = "tom";
}
console.log(new Person()); // {name:'tom', prototype: {age: 123}}
装饰器工厂(可以传参)
ts
function myDestroyed(params: any) {
console.log(params); // params 是传入的参数
return function (target:any){
console.log(target); // target 就是当前类
target.prototype.age = target;
}
}
@myDestroyed(123)
class Person {
public name: string = "tom";
}
console.log(new Person()); // {name:'tom', prototype: {age: 123}}
重载构造函数
ts
function logClass(target: any) {
console.log(target);
return class extends target {
apiUrl: any = "修改后的数据";
};
}
@logClass
class HttpClient {
public apiUrl: string= "构造函数里面的apiUrl";
}
console.log(new HttpClient().apiUrl); // '修改后的数据'
属性装饰器
ts
function logProperty(params:any){
console.log(params); // 333 params是传入的参数
return function(target:any,attr:any){
console.log(target); // 当前类
console.log(attr); // url 属性名
target[attr]=params;
}
}
class HttpClient{
@logProperty('333')
public url:any;
}
console.log(new HttpClient().url); // 333
方法装饰器
ts
function get(params: any) {
return function (target: any, methodName: any, desc: any) {
console.log(params); // 传入的参数
console.log(target); // 当前类
console.log(methodName); // getData 方法名
console.log(desc); // 描述符 { configurable:true enumerable:false value:ƒ getData() writable:true }
target.apiUrl = "xxxx"; // 添加到原型上
target.run = function () { // 添加到原型上
console.log("run");
};
};
}
class HttpClient {
public url: any | undefined;
@get("传入的参数")
getData() {
console.log(this.url);
}
}
var http: any = new HttpClient();
修改装饰器方法
ts
function get(params: any) {
return function (target: any, methodName: any, desc: any) {
console.log(params); // 传入的参数
console.log(target); // 当前类
console.log(methodName); // getData 方法名
console.log(desc); // 描述符 { configurable:true enumerable:false value:ƒ getData() writable:true }
const getData = desc.value; // 保存当前方法
desc.value = function (...arr:number[]){
// 做一些操作
const list: string[] = arr.map(item => String(item))
// 调用类的getData
getData.call(this,...list)
}
};
}
class HttpClient {
@get("传入的参数")
getData(...arr:number[]) {
console.log(arr,'我是getData');
}
}
var http: any = new HttpClient();
http.getData([1,2,3]) // ['1,2,3'] '我是getData'
属性装饰器
ts
function get(params: any) {
return function (target: any, methodName: any, index: any) {
console.log(params); // 传入的参数
console.log(target); // 当前类
console.log(methodName); // getData 方法名
console.log(index); // 0 参数的下标
};
}
class HttpClient {
getData(@get("传入的参数")arr:number[]) {
console.log(arr,'我是getData');
}
}
var http: any = new HttpClient();
装饰器执行顺序
- 属性 > 方法 > 方法参数 > 类
- 如果有多个同样的装饰器,它会先执行后面的
ts
@logClass1('api')
@logClass2('xxxx')
class HttpClient{
@logAttribute1()
@logAttribute2()
public apiUrl:string | undefined;
constructor(){
}
@logMethod1()
@logMethod2()
getData(){
return true;
}
setData(@logParams1() attr1:any,@logParams2() attr2:any,){
}
}
/*
属性装饰器2
属性装饰器1
方法装饰器2
方法装饰器1
方法参数装饰器2
方法参数装饰器1
类装饰器2
类装饰器1
*/
var http:any=new HttpClient();
function logClass1(params:string){
return function(target:any){
console.log('类装饰器1')
}
}
function logClass2(params:string){
return function(target:any){
console.log('类装饰器2')
}
}
function logAttribute1(params?:string){
return function(target:any,attrName:any){
console.log('属性装饰器1')
}
}
function logAttribute2(params?:string){
return function(target:any,attrName:any){
console.log('属性装饰器2')
}
}
function logMethod1(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法装饰器1')
}
}
function logMethod2(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法装饰器2')
}
}
function logParams1(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法参数装饰器1')
}
}
function logParams2(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法参数装饰器2')
}
}