装饰器执行时机
修饰器对类的行为的改变,是代码编译时发生的(不是TypeScript编译,而是js在执行机中编译阶段),而不是在运行时。这意味着,修饰器能在编译阶段运行代码。也就是说,修饰器本质就是编译时执行的函数。
在Node.js环境中模块一加载时就会执行
编译ts文件
tsc test1.ts –target ES5 –experimentalDecorators
类装饰器
1.参数为构造函数
1 2 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.成员的属性描述符
1 2 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、参数在函数参数列表中的索引。
1 2 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、成员的名字。
1 2 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、方法和属性装饰器,谁在前面谁先执行。因为参数属于方法一部分,所以参数会一直紧紧挨着方法执行