Typescript装饰器-简化基础

82 阅读3分钟

其实装饰器是一种注解,在各种框架使用了装饰器。例如:前端框架Angular和服务端框架Nestjs,由于自己需要学服务端框架Nestjs,装饰器在Nestjs中比较常见的。它还可以附加到方法、属性、类或者参数。这种装饰器的编译过程与我们平时的生活上有关系,例如说我的电脑里很多硬件,这种时候表示方法,硬件包括有内存条,显卡,硬盘等。有一些硬件损坏,需要去换新局部的硬件,而不是换整个电脑。

装饰器的语法比较简单,如果要使用装饰器,需要加上符号@即可,最后装饰器就会被调用到目标上。

1.开启装饰器

如果需要开启装饰器,首先找到tsconfig.json文件里找到experimentalDecorators开启即可。

2.装饰器工厂

需要一个装饰器如何应用到目标上,然后写一个装饰器工厂函数,这个相当于简单的装饰器,最后返回一个表达式。

const Base = (name:string) =>{
    // 使用相当于闭包
    const fn:ClassDecorator = (target) =>{
        target.prototype.__xiaobin = name
            target.prototype.fn = () =>{
                // console.log('我爱篮球')
            }
    }
    return fn
}

例上的代码,就是普通的装饰器,反正不管怎样最后是返回一个表达式。

3.类装饰器

类装饰器本身就是一种构造函数,应用于类构造函数,可以修改类定义。类装饰器英文称为ClassDecorator,target的参数是返回为类构造函数。

@deatil
class Info{
   greeting:string;
   constructor(message:stirng){
      this.greeting = message
   }
   greet() {
      return "world"+this.greeting
   }
}
console.log(new Info('james'));

用类装饰器@deatil,然后应用在Info类。

4.属性装饰器

属性装饰器在函数的传参一般是有两个:traget对于静态成员来说是类构造器,对于实例成员来说是类的原型链;另外是属性的名称。属性装饰器英文称为PropertyDecorator。

class Info{
    @format("hello,%c")
    greeting:string;
    constructor(message:string){
        this.greeting = message
    }
    greet(){
        let str = getFormat(this,"greeting")
        return str.replace("%c",this.greeting)
    }
}

@format()就是装饰器工厂,当被调用时,一般会读取格式的元数据。

5.参数装饰器

参数装饰器在构造函数参数有三种:traget对于静态成员来说是类构造器,对于实例成员来说是类的原型链; propertyKey为属性的名称(注意必须是方法的名称);index就是参数在方法中位置的下标。参数装饰器英文称为ParameterDecorator。

 const Result = () =>{
    const fn:ParameterDecorator = (target,key, index) =>{
        Reflect.defineMetadata('key','result',target)
    }
    return fn 
 }

前提是要安装reflect-metadata,这样方便获取到元数据。

6.方法装饰器

方法装饰器在函数中参数有:traget对于静态成员来说是类构造器,对于实例成员来说是类的原型链;propertyKey为属性的名称;descriptor为属性的描述器。方法装饰器英文称为MethodDecorator 和PropertyDescriptor。

 const Get = (url:string) =>{
    const fn:MethodDecorator = (target,_:any,descriptor:PropertyDescriptor) =>{
        const key = Reflect.getMetadata('key',target)
        axios.get(url).then(res=>{
            descriptor.value(key? res.data[key]:res.data)
        })
    }
    return fn
 }

其实方法装饰器和属性装饰器不同在于descriptor参数。通过这个参数可以修改方法的实现。

7.访问器装饰器

其实和方法装饰器一样的,但是区别在于参数为key不同,key有四种get、set、enumerable、configurable。

class Info{
    private point = {x:0,y:0}
    set pint(value:{x:number,y:number}){
       this.point = value;
    }
    get pint(){
        return this.point
     }
}

例上的把这个变量名改为不可修改值。