装饰器
装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为
通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能
常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法:普通装饰器(无法传参)、装饰参数器工厂(可传参)
类装饰器
类装饰器在类声明之前被声明(紧靠着声明类型),类装饰器应用于类构造函数,可以用来监视,修改或替换类定义,
//定义一个装饰器 function loge(params:any){ console.log(params) //输出当前类 } @loge class box{ constructor(){ } get(){ } }
编译后的js文件
我们可以在这params的原型链上添加方法或者属性,也就是给当前类的原型链上添加一个方法或者属性
//定义一个装饰器 function loge(params:any){ console.log(params) params.prototype.url='***' } @loge //不能有分号,挨着定义的类 class box{ constructor(){ } get(){ } } var box1=new box() console.log(box1)
console.log(box1.url)
装饰器工厂
function login(params:string){ return function(target:any){ console.log(target) console.log(params) } } @login("hello") class fun{ constructor(){ } get(){ } }
编译后的js文件
@login("hello")中的hello赋值于params,函数fun赋值于target
此时可以在target的原型链上添加方法
function login(params:string){ return function(target:any){ target.prototype.url=params } } @login("hello") class fun{ constructor(){ } get(){ } } var a=new fun() console.log(a.url)
类装饰器表达式会在运行时当做函数被调用,类的构造函数作为其唯一的参数
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明
function login(params:any){ console.log(params) } @login class fun{ api:string|undefined; constructor(){ this.api="我是fun中的api" } get(){ console.log(this.api) } } var a=new fun() a.get()
此时我们重载参数或者构造函数
比如我们现在可以在login中修改constructorapi的值
function login(params:any){ console.log(params) return class extends params{ api:any="我是修改的" get(){ console.log("我是修改的get") } } } @login class fun{ api:string|undefined; constructor(){ this.api="我是fun中的api" } get(){ console.log(this.api) } } var a=new fun() a.get()
属性装饰器
属性装饰器会在运行时当做函数调用,传入以下2个参数
//类装饰器 function login(params:any){ return function(target:any){ } } //属性装饰器 function log(params:any){ return function(target:any,attr:any){ } } @login("hello") class fun{ @log("word") api:string|undefined; constructor(){ this.api="我是fun中的api" } get(){ } } var a=new fun() a.get()
此时可以看到输出
attr就是属性的名称
target就是当前类原型对象
//类装饰器 function login(params:any){ return function(target:any){ // console.log(target) // console.log(params) } } //属性装饰器 function log(params:any){ return function(target:any,attr:any){ // console.log(target) // console.log(attr) target[attr]=params } } @login("hello") class fun{ @log("word") api:string|undefined; constructor(){ } get(){ console.log(this.api) } } var a=new fun() a.get()
方法装饰器
应用到方法,属性描述符上,可以用来监视,修改或替换方法定义
方法装饰会在运行时传入下列参数
- 对于静态变量成员来说是类的构造函数,对于实例成员或是类的原型对象
- 成员的名字
- 成员的属性描述符
//方法装饰器 function login(params:any){ return function(target:any,methodName:any,desc:any){ console.log(target) //如果这个方法是静态方法,那么输出的时类的构造函数,如果是实例成员,那就是原型对象 console.log(methodName) //方法名称 console.log(desc) //方法描述 } } class http{ url:any|undefined; constructor(){ } @login("http://www.baidu.com") get(){ } } var a=new http() a.get()
第一个参数输出一个原型对象,在这个原型对象上可以修改当前的这个类,扩展这个类的属性以及方法
第二个参数是当前方法的名称
第三个参数是描述信息,里面有当前的get方法
此时我们扩展一个属性和一个方法
//方法装饰器 function login(params:any){ return function(target:any,methodName:any,desc:any){ console.log(target) //如果这个方法是静态方法,那么输出的时类的构造函数,如果是实例成员,那就是原型对象 console.log(methodName) //方法名称 console.log(desc) //方法描述 target.api="*****" //扩展属性 target.run=function(){ //扩展方法 console.log(run) } } } class http{ url:any|undefined; constructor(){ } @login("http://www.baidu.com") get(){ console.log(this.url) } } var a:any=new http() console.log(a.api)
此时我们想要修改get方法,其实就是修改描述信息中desc.value
我们可以看一下
console.log(desc.value)
此时输出的这个方法就是get方法
方法修饰器可以修改当前的方法,可以把方法里面传入的参数改成string类型
//装饰器 function login(params:any){ return function(target:any,methodName:any,desc:any){ //console.log(target) //如果这个方法是静态方法,那么输出的时类的构造函数,如果是实例成员,那就是原型对象 // console.log(methodName) //方法名称 // console.log(desc.value) //方法描述 //修改这个装饰器的方法,把装饰器方法里面传入的所有参数改为string类型 //第一步保存当前的方法 var method=desc.value; //第二部修改当前的value desc.value=function(...args:any[]){ //把接收到的参数改为string类型 //循环遍历args这个数组,把数组里面的每一项转换为数组 args=args.map((value)=>{ return String(value) }) console.log(args) method.apply(this,args) //表示在这个方法里面,调用这个method,并且把这个args参数传入了 } } } class http{ url:any|undefined; constructor(){ } @login("http://www.baidu.com") get(...args:any){ console.log(args) console.log('我是get方法') } } var a:any=new http() a.get(123,'***')
方法参数装饰器
参数装饰器表达式会在运行时当做函数调用,可以使用参数装饰器为类的原型增加一些元素数据,传入3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
- 参数的名字
- 参数在函数参数列表中的索引
function login(params:any){ return function(target:any,paramsName:any,paramsIndex:any){ console.log(params) //u console.log(target) //当前类的原型对象 console.log(paramsName) //当前方法的名称 console.log(paramsIndex) //当前索引的位置 } } class http{ url:any|undefined; constructor(){ } //在方法的参数里面调用与类以及属性,方法上是一样的 get(@login('u')u:any){ console.log(u) console.log('我是get方法') } } var a=new http(); a.get(123)
参数装饰器为类的原型增加一些元素数据
function login(params:any){ return function(target:any,paramsName:any,paramsIndex:any){ console.log(params) //u console.log(target) //当前类的原型对象 console.log(paramsName) //当前方法的名称 console.log(paramsIndex) //当前索引的位置 //添加一个属性 target.api=params } } class http{ url:any|undefined; constructor(){ } //在方法的参数里面调用与类以及属性,方法上是一样的 get(@login('u')u:any){ console.log(u) console.log('我是get方法') } } var a:any=new http(); a.get(123) console.log(a.api)