装饰器:装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
写法:普通装饰器(无法传参) 、 装饰器工厂(可传参)。
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、装饰器执行顺序
属性 > 方法 > 方法参数 > 类
如果有多个同样的装饰器,它会先执行后面的