| 什么是装饰器
定义
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用 @expression
这种形式,@expression
求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。
通俗来讲就是在不动原来的方法的前提下,扩展方法的功能
是es7的标准特性
本质
装饰器本质上是一个函数,@expression
的形式其实是一个语法糖
注意
在 TS 中,装饰器仍然是一项实验性特性,未来可能有所改变,所以如果要使用装饰器,需要在 tsconfig.json 的编译配置中开启experimentalDecorators
,将它设为 true
装饰器的写法有两种
- 普通装饰器(不可传参)
- 装饰器工厂(可传参)
| 用法
- 类装饰器
给类动态扩展参数和方法
// 创建一个装饰器
function myDec(params:any) {
console.log(params); // 当前类Myclass
params.prototype.apiUrl = 'xxxx' // 给Myclass扩展(装饰)了一个属性
}
@myDec // 使用装饰器
class Myclass {
constructor() {
}
getData() {
}
}
重载类的属性和方法例子
function myDec(params:any) {
console.log(params); // 当前类Myclass
return class extends target {
apiUrl:any='我被重载了';
getData() {
console.log('我也被重载了')
}
}
}
@myDec // 使用装饰器
class Myclass {
public apiUrl:string |undefined
constructor() {
this.apiUrl = '我是构造函数的属性'
}
getData() {
console.log('我是方法')
}
}
- 装饰器工厂
装饰器工厂可以传参,其他普通装饰器不可以传参,
装饰器里返回一个方法就是一个装饰器工厂
// 创建一个装饰器工厂
function logClass(params:string) {
console.log(params); // 王一博
return function(target:any) {
console.log(target); // 当前类 Myclass
// TODO
target.prototype.name = params
}
}
@logClass('王一博') // 使用装饰器工厂并传参
class Myclass {
constructor() {
}
getData() {
}
}
let wyb = new Myclass()
console.log(wyb.name); // 王一博
- 属性装饰器 属性装饰器会在运行时当做函数被调用,传入下列2个参数
①对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
②属性
// 创建一个属性装饰器
function logProperty(params:string) {
// 两个参数
return function(target:any,attr:any) {
console.log(target); // 当前类 Myclass
console.log(attr); // 当前装饰器传的值 王一博
}
}
class Myclass {
@logProperty('王一博')
public name:any | undefined;
constructor() {
}
getData() {
}
}
let wyb = new Myclass()
console.log(wyb.name); // 王一博
- 方法装饰器 传三个参数
①静态成员是类的构造函数,实例对象是类的原型对象
②成员名字
③成员属性描述符
// 创建一个方法装饰器
function logMethod(params:string) {
console.log(params); // 王一博
// 三个参数
return function(target:any,methodName:any,desc:any) {
console.log(target); // 当前类 Myclass
console.log(methodName); // 当前方法name
console.log(desc); // Myclass的加了方法装饰器的方法对象
// 改写方法
desc.value = function(..args:any[]){
// 不改写方法,而是继承原来的方法
desc.value.apply(this,args)
}
}
}
class Myclass {
public name:any | undefined;
constructor() {
}
@logMethod('王一博')
getData() {
}
}
let wyb = new Myclass()
console.log(wyb.name); // 王一博
- 方法参数装饰器 给类的原型增加一些元素数据,传入参数有三
①当前类
②参数名称
③参数在函列表的索引
// 定义一个方法参数装饰器
function logParams(params:any) {
console.log(params) // 王一博
return function(target:any,methodName:any,attrIndex:any) {
console.log(target) // Myclass
console.log(methodName) // 方法名 getData
console.log(attrIndex) // 0
}
}
class Myclass {
constructor() {
}
getData(@logParams('王一博') name:any) {
}
}
- 装饰器执行顺序 属性装饰器--》方法装饰器(从上到下)--》方法属性装饰器(从右到左)-》类装饰器(从下到上)