typescript 装饰器

1、修改tsconfig.json
    "experimentalDecorators": true
    "emitDecoratorMetadata": true,    
	
	向装饰器传递参数得使用工厂函数写法
	
	四种装饰器返回值类型:
		ClassDecorator
		PropertyDecorator
		MethodDecorator
		ParameterDecorator

	类中不同声明上的装饰器将按以下规定的顺序应用:
	    参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员。
	    参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个静态成员。
	    参数装饰器应用到构造函数。
	    类装饰器应用到类。
  
    多个装饰器调用顺序:
   		当为普通函数时:从下往上
   		当为工厂函数时:先从上往下执行非返回的函数,然后从下往上执行返回的函数

2、使用
	(1)类装饰器
		(1)类装饰器表达式会在运行时当作函数被调用
			类装饰器应用于类构造函数,可以用来监视,修改或替换类定义,类装饰器不能用在声明文件中( .d.ts),也不能用在任何外部上下文中(比如declare的类).
	 	(2)接收一个参数,类的构造函数(类本身)作为其唯一的参数,参数.name返回类的名称。
		(3)如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
			即会用装饰器返回的类替换掉被装饰的类
		(4)装饰器在类定义时被调用,而不是创建实例时
		
		方式一:
			泛型继承一个有着多个参数的返回任意类型的函数,即构造函数或类
			function xx<T extends new (...args:any[])=>any>(constructor:T){
			
			    return class extends constructor{  类扩展构造函数,只能修改,不能增加属性
			    	增加/修改属性
				       	类中声明的属性名=值,不需要this
				     
				    增加方法
				    	方法名(){
				    		调用类属性需要this.属性名
				    	}
				    类实例调用增加的方法需要(对象 as any).方法名(),否则报错,解决方法二
			    }
			    
			}
			
			@xx
			@xx2 
			class 类{
				...
			}
			
		方式二:
			function  xx<T extends new (...args:any[])=>any>(constructor:T){
		        return class extends constructor{  //类扩展构造函数
					属性和方法的增加修改
		        }
			}
		
		
			const XX=xx(class {
			    属性:类型,
			    属性2:类型2
			    constructor(参数:类型){
			        this.属性=name;
			    }
			 }
			)
		
			const x=new XX(参数);
			xx.新增方法名();
			
		工厂模式使用装饰器:
			function xx(){
				return  xx<T extends new (...args:any[])=>any>(constructor:T){
			        return class extends constructor{  //类扩展构造函数
						属性和方法的增加修改
			        }
				}
			}
		
		
			const XX=xx()(class {
			    属性:类型,
			    属性2:类型2
			    constructor(参数:类型){
			        this.属性=name;
			    }
			 }
			)
		
			const x=new XX(参数);
			xx.新增方法名();

	(2)类的方法装饰器
		它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义
		1、方法装饰器返回一个属性描述符对象,会替代掉修饰的方法的属性描述符
			function xx(target:any,propertyKey:string,descriptor:PropertyDescriptor)
			{
				return{
					value:'xx',
					enumerable:false
				}
			}
		2、方法装饰器有三个参数
		    (1)静态方法来说是类的构造函数,普通方法是类的原型对象(prototype)。
			(2)方法的名字。
			(3)方法的属性描述符(value: [Function], writable: true,enumerable: true, configurable: true)。
		
			function xx(target:any,propertyKey:string,descriptor:PropertyDescriptor)
			{
					descriptor.value就是该方法的引用
					可以设置方法不可修改等操作
			}
			class X{
				...
				@xx
				方法名(){
					...
				}
			}
			
		工程模式传递参数:
			function xxx(msg:string){
				function xx(target:any,propertyKey:string,descriptor:PropertyDescriptor)
				{
						descriptor.value就是该方法的引用
						可以设置方法不可修改等操作
				}
			}
			class X{
				...
				@xxx('错误提示')
				方法名(){
					...
				}
			}

	(3)访问器装饰器(setter和getter)
		在使用set和get之前调用,即类定义时
		(1)该装饰器只能在get/set上使用一个,因为它联合了get和set访问器
		(2)访问器装饰器返回一个属性描述符对象,会替代掉修饰的方法的属性描述符
			function xx(target:any,propertyKey:string,descriptor:PropertyDescriptor)
			{
				return{
					value:'xx',
					enumerable:false
				}
			}
		(3)访问器的三个参数
			(1)静态方法来说是类的构造函数,普通方法是类的原型对象(prototype)。
			(2)方法的名字。
 			(3)方法的属性描述符(set:func,get:func, writable: true,enumerable: true, configurable: true)。
 			
 			function xx(target:any,propertyKey:string,descriptor:PropertyDescriptor)
			{
				...
			}
			
			class X{
					..	
			    get name(){
			        return this._name;
			    }
			
			    @xx
			    set name(name:string){
			        this._name=name;
			    }
			 }

	(4)属性装饰器
		给类的属性使用,用来监视类中是否声明了某个名字的属性。 
		有两个参数
			(1)静态属性来说是类的构造函数,普通属性是类的原型对象(prototype)。
			(2)属性的名字。
			
	 		function xx(target:any,propertyKey:string):any
			{
				通过target[key]修改的是类原型上的属性,不是对象原型上的属性
				
				如果要修改属性的访问修饰符,需要返回一个descriptor来替换原始的descriptor
			    const descriptor:PropertyDescriptor={
			        writable:false
			    }
			    return  descriptor;
			}
			
			class Test{
			    @xx
			    name='xxx';
			 }
			 
	(5)参数装饰器
		有三个参数
		(1)静态属性来说是类的构造函数,普通属性是类的原型对象(prototype)。
		(2)属性的名字。
		(3)参数在函数参数列表中的索引。

		使用:在需要装饰的参数前面放置
		
		function xx(target:any,propertyKey:string,parameterIndex: number)
		{
			...
		}
		
		class X{
		    getInfo( 参数:类型,@xx 参数:类型){
					...	
		    }	
		}	

代码示例:
类装饰器:

//类装饰器
//泛型继承一个多个参数的返回任意类型的函数,即构造函数
//泛型继承一个多个参数的返回任意类型的函数,即构造函数

   function testDecorator<T extends new (...args:any[])=>any>(constructor:T){
       return class extends constructor{  //类扩展构造函数
           name='jacky'
           name3='kacj'
           getName()
           {
               console.log(this.name);
           }
       }
   }



@testDecorator
class Test{
    name:string;
    name3:string;
    constructor(name:string){
        this.name=name;
    }
}



const test =new Test('jeff');
console.log(test.name3);
(test as any).getName();

//装饰器装饰后的类
//泛型继承一个多个参数的返回任意类型的函数,即构造函数
function testDecorator(){
    return function <T extends new (...args:any[])=>any>(constructor:T){
        return class extends constructor{  //类扩展构造函数
            name='jacky'
            name3='kacj'
            getName()
            {
                console.log(this.name);
            }
        }
    }
}

// function  testDecorator<T extends new (...args:any[])=>any>(constructor:T){
//         return class extends constructor{  //类扩展构造函数
//             name='jacky'
//             name3='kacj'
//             getName()
//             {
//                 console.log(this.name);
//             }
//         }
// }

// const Test=testDecorator(class Test{
//     name:string;
//     name3:string;
//     constructor(name:string){
//         this.name=name;
//     }
//  }
// )

const Test=testDecorator()(class Test{
    name:string;
    name3:string;
    constructor(name:string){
        this.name=name;
    }
 }
)




const test =new Test('jeff');
console.log(test.name3);

方法装饰器:

/**
 * 
    对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
    成员的名字。
    成员的属性描述符。

 * @param key 
 */
function nameDecorator(target:any,propertyKey:string,descriptor:PropertyDescriptor)
{
	descriptor.value=function(){
		return '修改了'	
	}
}

class Test{
    name:string;
    name3:string;
    constructor(name:string){
        this.name=name;
    }

    @nameDecorator
    getName(){
        return this.name;
    }
 }

const test =new Test('jeff');
console.log(test.getName())

//检测参数函数调用是否有问题实例
const userInfo:any=undefined;
function catchError(target:any,key:string,descriptor:PropertyDescriptor)
{
    const fn=descriptor.value;
    descriptor.value=function(){
        try{
            fn();
        }catch(e)
        {
            console.log('userinfo有问题');
        }
    }
}


class Test {
    @catchError
    getName()
    {
        return userInfo.name;
    }
    getAge()
    {
        return userInfo.age;
    }
}

const test = new Test();
test.getName();

访问器装饰器:

function visitDecorator(target:any,propertyKey:string,descriptor:PropertyDescriptor)
{
    descriptor.get=function(){
        console.log('修改了');
    }
    // console.log(descriptor.get);
}

class Test{
    private _name:string;
    constructor(name:string){
        this._name=name;
    }

    get name(){
        return this._name;
    }

    @visitDecorator
    set name(name:string){
        this._name=name;
    }
 }





const test =new Test('jeff');
// test.name='jeff shuai';
// console.log(test.name);

属性装饰器:


function nameDecorator(target:any,propertyKey:string):any
{
    const descriptor:PropertyDescriptor={
        writable:false
    }
    return  descriptor;
}

class Test{
    @nameDecorator
    name='tom';
    // constructor(name:string){
    //     this._name=name;
    // }
 }





const test =new Test();
// test.name='jacky'
console.log(test.name);

参数装饰器:

function arguementDecorator(target:any,propertyKey:string,parameterIndex: number)
{
    console.log(parameterIndex);
}

class Test{

    
    getInfo( name:string,@arguementDecorator age:number){

    }
 }





const test =new Test();
// test.name='jacky'
test.getInfo('jeff',30);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值