在一些场景下我们需要额外的特性来支持标注或修改类及其成员。 装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上。有普通装饰器(无参数),和装饰工厂(有参数)两种
1。类装饰器:可以扩展当前类的属性和方法
1.1无参数的类装饰器(普通装饰器)
function logInfo(target:any/*装饰的类的构造函数*/){
console.log(target)
target.prototype.name = '张三'
target.prototype.getName = function(){
console.log(this.name)
}
}
@logInfo//调用装饰器
class Info{
constructor(){
}
}
let foo = new Info();
console.log(foo);
foo.getName();
1.2有参数的类装饰器(装饰工厂)
function logInfo(params:any){
return function(target:any){
console.log(params);
console.log(target);
target.prototype.name = params;
target.prototype.getName = function(){
console.log(this.name)
}
}
}
@logInfo('张三')//调用装饰器
class Info{
constructor(){
}
}
let foo = new Info();
console.log(foo);
foo.getName();
1.3用类装饰器来重载类的构造函数
function logInfo(target:any){
return class extends target{
name:string = '李四';
getName(){
console.log(this.name)
}
}
}
@logInfo//调用装饰器
class Info{
public name:string|undefined;
constructor(na:string){
this.name = na;
}
getName(){
console.log(this.name)
}
}
let foo = new Info('张三');
console.log(foo);
foo.getName();
2.属性装饰器
function logProperty(params:any){
return function(target:any,attr:any){
//target 装饰器如果修饰静态属性,就是当前类,如果修饰非静态属性,就是类的构造函数的原型对象
console.log(attr)
target[attr] = params;//如果在类中给属性赋值了(或者在构造函数中赋值),这里修改属性的值是无效的
}
}
class Info{
@logProperty('李四')
public name:string|undefined;
// public name:string|undefined = '张三';
constructor(){
}
getName(){
console.log(this.name)
}
}
let foo = new Info();
console.log(foo);
foo.getName();
3.方法装饰器
function logMethods(params:any){
return function(target:any,methodsName:any,desc:any){
//target 装饰静态方法就是当前类,装饰非静态方法,就是当前类的构造函数的原型对象
//methodsName 装饰当前方法的名称
//desc 装饰的当前方法的描述,decs.value可获取当前方法
// console.log(params)
// console.log(target)
// console.log(methodsName)
// console.log(desc)
//修改装饰器的方法,把传入方法的参数全部改为string类型,并把装饰的参数注入
let oMetod = desc.value;//保存装饰方法
desc.value = function(...args:Array<any>){
args.push(params)
args = args.map((arg)=>{
return String(arg)
})
oMetod.call(this,args)//调用装饰方法
}
}
}
class Info{
public name:string|undefined;
constructor(){
}
@logMethods('李四')
getName(...args:any[]){
console.log(args)
}
}
let foo = new Info();
foo.getName('张三',25);
4.方法参数装饰器
function logParams(params:any){
return function(target:any,methodsName:any,index:any){
//target 当前类的构造函数的原型对象
//methodsName 装饰的当前方法名称
//index 参数的索引下标(第几个参数)
target.kk = 'kk';//在原型对象上绑定属性
console.log(params)
console.log(target)
console.log(methodsName)
console.log(index)
}
}
class Info{
public name:string|undefined;
constructor(){
}
getName(ha:any,@logParams('张三') name:any){
}
}
let foo:any = new Info();
console.log(foo.kk)//访问原型对象上的属性
5.装饰器执行顺序,属性装饰器-->方法参数装饰器-->方法装饰器-->类装饰器;多个装饰器修饰则从上到下,从右到左执行
function logProperty1(params?:any){
return function(target:any,attr:any){
console.log('属性装饰器1')
}
}
function logProperty2(params?:any){
return function(target:any,attr:any){
console.log('属性装饰器2')
}
}
function logParams1(params?:any){
return function(target:any,methodsName:any,index:any){
console.log('方法参数装饰器1')
}
}
function logParams2(params?:any){
return function(target:any,methodsName:any,index:any){
console.log('方法参数装饰器2')
}
}
function logParams3(params?:any){
return function(target:any,methodsName:any,index:any){
console.log('方法参数装饰器3')
}
}
function logMethods1(params?:any){
return function(target:any,methodsName:any,desc:any){
console.log('方法装饰器1')
}
}
function logMethods2(params?:any){
return function(target:any,methodsName:any,desc:any){
console.log('方法装饰器2')
}
}
function logInfo1(params?:any){
return function(target:any){
console.log('类装饰器1')
}
}
function logInfo2(params?:any){
return function(target:any){
console.log('类装饰器2')
}
}
@logInfo1()
@logInfo2()
class Info{
@logProperty1()
@logProperty2()
public name:string|undefined
constructor(){
console.log('构造函数')
}
@logMethods1()
@logMethods2()
getName(@logParams1() @logParams2() name:string,@logParams3() age:number){
}
}
let info = new Info()