08_TypeScript装饰器

装饰器:装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。

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

1、类装饰器:类装饰器在类声明之前被声明(紧靠着类声明),类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。 传入一个参数。

类装饰器:普通装饰器(无法传参)

//定义一个装饰器(其实就是一个方法)
function decorator(target:any){
    //target 就是当前类
    console.log(target);
    //扩展属性
    target.prototype.name='扩展属性';
    //扩展方法
    target.prototype.run=function(){
        console.log('扩展方法');
    }
}
//定义一个类并装饰(用符号@+装饰器名称,紧靠着类声明)
@decorator
class Dog{
    constructor(){}
    eat(){}
}
//调用扩展后的属性及方法
var dog:any = new Dog();
dog.name;
dog.run();

类装饰器:装饰器工厂(可传参)

//定义一个装饰器(其实就是一个方法)
function decorator(params:string){
    return function(target:any){
        //target 就是当前类
        console.log(target);
        //params 是自定义传入得参数
        console.log(params);
        //扩展属性
        target.prototype.name= params+'扩展属性';
        //扩展方法
        target.prototype.run=function(){
            console.log(params+'扩展方法');
        }
   }
}
//定义一个类并装饰(用符号@+装饰器名称,紧靠着类声明),及传参
@decorator('张三')
class Dog{
    constructor(){}
    eat(){}
}
//调用扩展后的属性及方法
var dog:any = new Dog();
dog.name;
dog.run();

类装饰器:重载构造函数

//定义一个装饰器(其实就是一个方法)
function decorator(target:any){
    //target 就是当前类
    console.log(target);
    //重载构造函数(定义一个类并继承当前类,修改原有的属性值及方法)
    return class extends target{
        name:any = '小黑有钱了'
        eat(){
            console.log(this.name + '而且变帅了')
        }
    }
}
//定义一个类并装饰(用符号@+装饰器名称,紧靠着类声明)
@decorator
class Dog{
    public name:string | undefined;
    constructor(){
        this.name = "小黑"
    }
    eat(){
        console.log(this.name+'吃东西')
    }
}
//调用扩展后的属性及方法
var dog:any = new Dog();
dog.name;
dog.eat();

2、属性装饰器 :属性装饰器表达式会在运行时当作函数被调用。

//定义一个装饰器(其实就是一个方法)
function decorator(params:any) {
    //属性装饰器传入俩个参数,原型对象和成员名字
    return function(target: any, attr: any) {
        target[attr]=params;
    }
}
class Demo {
    //定义一个属性并装饰(用符号@+装饰器名称,紧靠着属性声明)
    @decorator('张三') 
    public name:any |undefined;
    constructor(){}
}

const d = new Demo();
console.log(d.name);//张三

3、方法装饰器:可以用来监视,修改或者替换方法定义。

//定义一个装饰器(其实就是一个方法)
function get(params:any){
    console.log(params)
    //方法装饰器传入三个参数,原型,成员名字,成员描述
    return function(target:any,methodName:any,desc:any){
        //desc.value 原来的方法
        var oMethod=desc.value;
        //覆盖原来的方法
        desc.value=function(){                
            console.log('张三有钱了');
            //如果是修改原来的方法,而不是覆盖,
            //oMethod.apply(this);
        }
    }
}
class HttpClient{  
    public url:any |undefined;
    constructor(){
    }
    //定义一个方法并装饰(用符号@+装饰器名称,紧靠着方法声明),及传参
    @get('方法装饰器')
    getData(){
        console.log('张三很穷');
    }
}
var http=new HttpClient();
http.getData();

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

//定义一个装饰器(其实就是一个方法)
function PathParam(params:any) {
    //方法参数装饰器传入三个参数,原型,方法的名字,参数在函数参数列表中的索引
    return function (target:any,methodName:any,paramsIndex:any){
        //扩展属性
        target.apiUrl=params;
    }
}

class Demo {
    constructor() { }
    //定义个方法并装饰(用符号@+装饰器名称,以传参的形式写入方法)
    getUser( @PathParam("userId") userId: string) {
        console.log(userId)
    }
}
var http:any = new Demo();
http.getUser(123456);
console.log( http.apiUrl);

5、装饰器执行顺序

  属性 > 方法 > 方法参数 > 类
  如果有多个同样的装饰器,它会先执行后面的

猜你喜欢

转载自www.cnblogs.com/MaShuai666/p/12368294.html