Typescript拓展 - 装饰器(Decorator)

装饰器介绍以及基本使用

  • 装饰器:就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
  • 常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器
  • 装饰器的写法:普通装饰器(无法传参) 、 装饰器工厂(可传参)
  • 装饰器是过去几年中js最大的成就之一,已是Es7的标准特性之一

1. 类装饰器(无法参数)

  • 类装饰器在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。 传入一个参数
// 定义一个函数(装饰器)
function fun( target:any ){
// 相当于给Person这个类的原型上添加一个userName属性且值为:lam
target.prototype.userName = 'lam';
}

/*
在类的外层使用@关键字套上上面定义的函数组装成装饰器(理解为人在外面穿衣服)
装饰器会自动将该类传入个装饰器函数并由target形参接收
*/
@fun
class Person{

}

// 实例化一个类
let p1 = new Person();
//@ts-ignore
console.log( p1.userName );// 成功输出lam

2. 装饰器工厂(可传参)

// 装饰器工厂相当于在在类装饰器的外部再套上一个函数再以返回值的形式将类装饰器返回给对应类
function fun1( options:any ){
// 返回一个类装饰器,并将接受回来的参数传递给下面的类
return ( target:any )=>{
target.userName = options.name;
target.prototype.age = options.age;
}
}

// 传递 options 参数给上面的装饰器工厂
@fun1({
name:'lam',
age:18
})
class Obj1{

}
let obj1 = new Obj1();
//@ts-ignore
console.log(obj1.name , obj1.age );// lam 18

3. 装饰器组合

function demo1( target:any ){
console.log('demo1')
}
function demo2( ){
console.log('demo2')
return ( target:any )=>{
console.log('demo2里面')
}
}
function demo3( ){
console.log('demo3')
return ( target:any )=>{
console.log('demo3里面')
}
}
function demo4( target:any ){
console.log('demo4')
}

@demo1
@demo2()
@demo3()
@demo4
class Person{

}

/*结果是:
demo2
demo3
demo4
demo3里面
demo2里面
demo1
*/

结合起来一起使用的时候, 会先 从上至下 的执行所有的装饰器工厂, 拿到所有真正的装饰器, 然后再 从下至上 的执行所有的装饰器:

5. 属性装饰器

/*
属性装饰器顾名思义是用来装饰一个类中的属性的
*/
// arg为传递的参数
function fun3( arg:any ){
// 这里的target为对应的类,arrt为对应类中要装饰的属性
return ( target:any , attr:any )=>{
// 我们也可以这样来获取对应的属性
// console.log(target,attr)// 对应的类,对应的属性
target[attr] = arg;
}
}

class Obj3{
@fun3('lam')
//@ts-ignore
userName:string
}
let obj3 = new Obj3();
console.log( obj3.userName );// lam

6. 方法装饰器

// 方法装饰器与上面的属性装饰器基本一致(也可以使用工厂的形式接受以及传递参数)
function test( target: any, propertyKey: string, descriptor: PropertyDescriptor ) {
console.log( target );// 对应的类本身
console.log( propertyKey );// 方法名
console.log( descriptor );// 对应方法的一些属性
}

class Person {
@test
sayName() {
console.log( 'say name...' )
return 'say name...';
}
}

let p = new Person();
p.sayName()