
1.什么是前端器装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明,好叫方法,装饰访问符,前端器属性和参数上。好叫
装饰器是装饰一个表达式 表达式被执行后,返回一个函数 函数的前端器输入参数为:target,name和descriptor 执行函数后,好叫可能返回descriptor对象,装饰用于配置target对象 装饰器使用@expression形式,前端器expression求值后必须返回一个函数,好叫他会在运行时被调用,装饰被装饰的前端器声明信息作为参数传入。
例如:
// 定义装饰器 function testDecorator(target: any,好叫 key: string): void { console.log("Target: ", target ); console.log("key: ", key); } // 使用装饰器 class Boat{ color: string = "yellow"; get formattedColor(): string{ return `this boat color is ${ this.color}`; } @testDecorator pilot(): void{ console.log("swish"); } } // 实例化 const boat = new Boat(); boat.pilot(); console.log(boat.formattedColor); 运行得到:
Target: { } key: pilot swish this boat color is yellow 2.装饰器分类
装饰器根据其所装饰的类型分为以下一种:
类装饰器 属性装饰器 方法装饰器 参数装饰器 若要启用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用experimentalDecorators编译器选项:
命令行:
tsc --target ES5 --experimentalDecorators tsconfig.json:
{ "compilerOptions": { "target": "ES5",装饰 "experimentalDecorators": true } } 2.1 类装饰器
类装饰器用于类构造函数,进行监听、修改或替换类定义,在类声明之前进行声明(紧挨着类声明)。
切记:
类装饰器不能用在声明文件中(.d.ts),也不能用在任何外部上下文中。 类装饰器表达式会在运行时当作函数被调用,服务器租用类的构造函数作为其唯一的参数。 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。 如果你要返回一个新的构造函数,你必须注意处理好原来的原型链。在运行时的装饰器调用逻辑中不会为你做这些。 类装饰器声明:
declare type ClassDecorator = <TFunction extends Function>( target: TFunction )=>TFunction | void; 类装饰器顾名思义,就是⽤来装饰类的。它接收⼀个参数:
target: TFunction - 被装饰的类 栗子:
// 类装饰器 function classDecorator(constructor: typeof Boat){ console.log(constructor); } // 使用类装饰器 @classDecorator class Boat{ } 运行结果:
[class Boat] 2.2 方法装饰器
方法装饰器用于方法的属性描述符,可以进行监听、修改或替换方法定义,在待修饰方法声明前进行声明。方法装饰器不能用在声明文件(.d.ts),重载或者任何外部上下文中。
方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
target:被装饰的类 key: 方法名 descriptor: 属性描述符 「注意:如果代码输出目标版本小于ES5,源码下载属性描述符将会是undefined。」
如果方法装饰器返回一个值,它会被用作方法的属性描述符。
举个栗子:
// 定义装饰器 function testDecorator(target: any, key: string): void { console.log("Target: ", target ); console.log("key: ", key); } function logError(errorMessage: string){ return function(target: any, key: string, desc: PropertyDescriptor){ const method = desc.value; desc.value = function(){ try { method(); }catch(err){ console.log(errorMessage); } } } } // 使用装饰器 class Boat{ color: string = "yellow"; @testDecorator get formattedColor(): string{ return `this boat color is ${ this.color}`; } @logError("Oops boat was sunk in ocean") pilot(): void{ throw new Error() console.log("swish"); } } // 实例化 const boat = new Boat(); boat.pilot(); 运行得到:
Target: { } key: formattedColor Oops boat was sunk in ocean 2.3 属性装饰器
属性装饰器属性描述符只能用来监视类中是否声明了某个名字的属性,在属性声明前进行声明。
属性装饰器表达式会在运行时当做函数进行调用,传入两个参数:
target: 被装饰的类 key: 被装饰类的属性名字 注意:属性描述符不作为参数传入属性装饰器。因为目前还没有办法在定义一个原型对象时描述一个实例属性,并且没有办法进行建议监听或修改一个属性的初始化方法。
// 定义装饰器 function testDecorator(target: any, key: string): void { console.log("Target: ", target ); console.log("key: ", key); } function logError(errorMessage: string){ return function(target: any, key: string, desc: PropertyDescriptor){ const method = desc.value; desc.value = function(){ try { method(); }catch(err){ console.log(errorMessage); } } } } // 使用装饰器 class Boat{ @testDecorator color: string = "yellow"; // @testDecorator get formattedColor(): string{ return `this boat color is ${ this.color}`; } @logError("Oops boat was sunk in ocean") pilot(): void{ throw new Error() console.log("swish"); } } 运行结果:
Target: { } key: color 2.4 参数装饰器
参数装饰器用于类构造函数或方法声明。接收三个参数:
target: 被装饰的类 key:方法名 index:方法中的参数索引值 // 定义装饰器 function testDecorator(target: any, key: string): void { console.log("Target: ", target ); console.log("key: ", key); } function logError(errorMessage: string){ return function(target: any, key: string, desc: PropertyDescriptor){ const method = desc.value; desc.value = function(){ try { method(); }catch(err){ console.log(errorMessage); } } } } // 参数装饰器 function parameterDecorator(target: any, key: string, index: number){ console.log(key, index); } // 使用装饰器 class Boat{ @testDecorator color: string = "yellow"; // @testDecorator get formattedColor(): string{ return `this boat color is ${ this.color}`; } @logError("Oops boat was sunk in ocean") pilot(): void{ throw new Error() console.log("swish"); } fast( @parameterDecorator speed: string, @parameterDecorator generateWake: boolean ): void{ if(speed === "fast"){ console.log("swish"); }else{ console.log("nothing"); } } } 运行结果:
Target: { } key: color fast 1 fast 0 小结
我们看到装饰器很方便为我们结果了许多问题。装饰器根据其装饰的对象不同,分为:类装饰器、属性装饰器、方法装饰器、参数装饰器。