装饰器执行时机
修饰器对类的行为的改变,是代码编译时发生的(不是TypeScript编译,而是js在执行机中编译阶段),而不是在运行时。这意味着,修饰器能在编译阶段运行代码。也就是说,修饰器本质就是编译时执行的函数。
在Node.js环境中模块一加载时就会执行
编译ts文件
tsc test1.ts –target ES5 –experimentalDecorators
类装饰器
1.参数为构造函数
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | function Path(path: string) {return function(targer: Function) {
 !targer.prototype.config && (targer.prototype.config = {})
 targer.prototype.config.baseUrl = path;
 }
 }
 
 @Path('/url')
 class Service {
 constructor(){}
 }
 
 console.log((<any>Service.prototype).config)    // { baseUrl: '/url' }
 let service = new Service()
 console.log((<any>service).config)              // { baseUrl: '/url' }
 
 | 
方法装饰器
1.静态方法是构造函数,成员函数是类的原型对象
2.成员的名字
3.成员的属性描述符
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | function Get(path: string): any {return function(targer, methodName: string, descriptor: PropertyDescriptor) {
 !targer.config && (targer.config = {})
 targer.config[methodName] = path;
 }
 }
 
 class Service {
 @Get('user')
 getUser() {}
 
 constructor(){}
 }
 
 console.log((<any>Service.prototype).config)    // { getUser: 'user' }
 let service = new Service()
 console.log((<any>service).config)              // { getUser: 'user' }
 
 | 
Get 的返回值要为any,否则tsc编译时候报错: Unable to resolve signature of method decorator when called as an expression
方法参数装饰器
1、对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、参数的名字。
3、参数在函数参数列表中的索引。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | function PathParam(path: string) {return function(target, paramName: string, index: number) {
 !target.config && (target.config = {})
 target.config[index] = path;
 }
 }
 
 class Service {
 getUser(@PathParam('userID') userid: string, @PathParam('userName') name: string) {}
 
 constructor(){}
 }
 
 console.log((<any>Service.prototype).config)  // { '0': 'userID', '1': 'userName' }
 
 | 
属性装饰器
1、对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、成员的名字。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | function DefaultValue(value: string) {return function(target, propertyName: string) {
 !target.config && (target.config = {})
 target.config[propertyName] = value;
 }
 }
 class Service {
 
 @DefaultValue("0")
 value: string
 
 constructor(){}
 }
 
 console.log((<any>Service.prototype).config)  // { value: '0' }
 
 | 
装饰器加载顺序
1、有多个参数装饰器时:从最后一个参数依次向前执行
2、方法和方法参数中参数装饰器先执行。
3、类装饰器总是最后执行。
4、方法和属性装饰器,谁在前面谁先执行。因为参数属于方法一部分,所以参数会一直紧紧挨着方法执行