什么是装饰器
装饰器是给一个方法,属性或类扩展一些新的行为,而不是去直接修改它本身的一个函数。
如果在项目中要使用装饰器,需要在 tsconfig.json
的编译配置中开启experimentalDecorators
,将它设为 true
。
使用装饰器
先定义一个函数,这个函数有一个参数,就是要装饰的目标,装饰的作用不同,这个target
代表意思也不同。定义了这个函数之后,它就可以作为装饰器,使用@函数名
的形式,写在要装饰的内容前面。
function f (taget: any, propertyKey:String) {
console.log('propertyKey:',propertyKey) //propertyKey: run
}
//定义一个Person类
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
@f
run(): void {//方法
console.log(this.name+ "在跑步");
}
}
var p = new Person("张三");
p.run();//张三在跑步
装饰器组合
装饰器可以组合使用,也就是对于同一个目标,使用多个装饰器。
// 可以写在一行
@setName @setAge
// 可以换行
@setName
@setAge
target
需要注意,多个装饰器的执行顺序:
装饰器工厂从上到下依次执行,但是只是用于返回函数但不调用函数;
装饰器函数从下到上依次执行,也就是执行工厂函数返回的函数。
function setName () {
console.log('get setName')
return function (target) {
console.log('setName')
}
}
function setAge () {
console.log('get setAge')
return function (target) {
console.log('setAge')
}
}
//定义一个Person类
@setName() @setAge()
class Person {
name: string;
age: number;
constructor(name: string) {
this.name = name;
}
run(): void {//方法
console.log(this.name+ "在跑步");
}
}
var p = new Person("张三");
p.run();//张三在跑步
// get setName
// get setAge
// setAge
// setName
// 张三在跑步
类装饰器
类装饰器在类声明之前声明,它有唯一的参数target
,就是装饰的这个类。
通过装饰器,就可以修改类的原型对象和构造函数
function setName (name: string) {
return function (target: Function) {
console.log('setName')
}
}
function addName(constructor: Function) {
constructor.prototype.name = "小浩";
}
@setName('里斯')
@addName
class Person {
name: string;
age: number;
constructor() {}
}
const person = new Person();
console.log(person.name); //小浩
方法装饰器
方法装饰器用来处理类中方法,它可以处理方法的属性描述符,可以处理方法定义。方法装饰器在运行时也是被当做函数调用,含 3 个参数:
装饰静态成员时是类的构造函数,装饰实例成员时是类的原型对象
装饰方法的名字
装饰方法的属性描述符
function logmethod (bool: boolean):any {
return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
console.log(propertyName) // run
console.log(descriptor) // {writable: true, enumerable: false, configurable: true, value: ƒ}
//修改属性描述
// descriptor.enumerable = bool;
return {
value: function() {
return 28;
},
enumerable: bool
};
}
}
class Person {
name: string;
age: number;
constructor() {
}
@logmethod(false)
getAge ():any {//方法
return this.age;
}
}
const p = new Person();
console.log(p.getAge());
属性装饰器
属性装饰器声明在属性声明之前,它有 2 个参数,和方法装饰器的前两个参数是一样的。
属性装饰器没法操作属性的属性描述符,它只能用来判断某各类中是否声明了某个名字的属性。
function printPropertyName(target: any, propertyName: string) {
console.log(propertyName);
}
class Info {
@printPropertyName // name
name: string;
@printPropertyName // age
age: number;
}
参数装饰器
参数装饰器,顾名思义是用于修饰参数的装饰器。
function logName (target: Object, propertyKey: string, index: number) {
console.log(target) //{constructor: ƒ, work: ƒ}
console.log(propertyKey) //work
console.log('logName',index) // 0
}
function logdoname (target: Object, propertyKey: string, index: number) {
console.log(target) //{constructor: ƒ, work: ƒ}
console.log(propertyKey) //work
console.log('logdoname',index) // 1
}
class Person {
name: string;
age: number;
constructor() {
}
work (@logName name:string,@logdoname doname:string):any {//方法
console.log(name + '在' + doname)
}
}
const p = new Person();
p.work('小浩','工作')
参数装饰器有三个参数 target、propertyKey、index
:
target:当前对象的原型
propertyKey:参数的名称
index:参数数组中的位置,比如上例中参数 name 的位置是 0, doname 的位置为 1