概念
装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以允许使用@<name>注释标记一次性修改类或类成员的行为。
启用方式
- 在tsconfig文件中修改配置:"compilerOptions": { "target": "ES5", "experimentalDecorators": true }
- 在命令行输入命令:tsc --target ES5 --experimentalDecorators
使用方法
普通装饰器写法:不能传参
// 定义普通装饰器
function writeClass(params: any) {
// 不能传参,即params为当前类
params.prototype.baseSize = '20px';
params.prototype.write = function() {
// write方法
}
}
// 定义类,并用普通装饰器装饰
@writeClass
class Read {
constructor(){}
}
// 实例化类
let w: any = new Read();
console.log(w.baseSize); // 调用装饰器封装的属性
装饰器工厂写法:可以传参
// 定义装饰器工厂
function writeClass(params: string) {
return function(target: any) {
target.prototype.baseSize = params; // params传参
}
}
// 定义类,并用装饰器装饰,并传参
@writeClass('30px')
class Read {
constructor(){}
}
// 实例化类
let w: any = new Read();
console.log(w.baseSize); // 调用装饰器封装的属性,通过传参控制的值
分类
类装饰器
上述例子即为类装饰器,他的表达式在运行时当做函数被调用
属性装饰器
属性装饰器的表达式在运行时也被当做函数调用,但是他传三个参数值,
target(对于静态成员来说是类的构造函数;对于实例成员来说是类的原型对象)、
name(成员名称)、
descriptor(成员的属性描述符)。
与Object.defineProperty的三个参数用法类似。
// 定义属性装饰器
function readonly(value: boolean) {
return function (target: any, name: string, descriptor: PropertyDescriptor) {
descriptor.writable = value;
}
}
class Person {
// 定义属性,并用装饰器装饰,传参
@readonly(false)
married() {
console.log('我只能查看,不能修改');
}
}
const e = new Person();
e.married();
方法装饰器
同属性装饰器类似,他也传3个参数target、propertyName、descriptor
参数装饰器
他传入的3个参数分别是target、name、index(参数在函数参数列表中的索引)
// 定义参数装饰器
function write(param: string) {
return function (target: any, name: string, index: number) {
console.log(index)
}
}
class Person {
// 定义方法并修饰参数装饰器,传参
write(@write('paper') size: string, @write('A4') name: string) {
console.log('方法调用');
}
}
// paper
// A4
// 1
// 0
各装饰器的执行顺序
如果在一段代码中同时定义了1个方法装饰器、1个类装饰器、1个属性装饰器、2个参数装饰器。
执行顺序为:属性装饰器 > 参数2装饰器 > 参数1装饰器 > 方法装饰器 > 类装饰器