简介
介绍:装饰器是一种特殊类型的声明,它能够被附加到类,方法, 访问器,属性或参数上。用 @添加
装饰器本质上还是一个函数,在别的语言中已广泛使用,如: python, 但在TS中依旧为一个测试中的版本,若要启 用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用experimentalDecorators编译器选项
添加到类上, 类装饰器
添加到方法上,方法装饰器
添加到访问器上,访问器装饰器
添加到属性上,属性装饰器
添加到参数上,参数装饰器
装饰器工厂:如果我们要定制一个修饰器如何应用到一个声明上,我们得写一个装饰器工厂函数。 装饰器工厂就是一个简 单的函数,它返回一个表达式,以供装饰器在运行时调用
类的装饰器
- 类装饰器就在类声明之前被声明
- 类装饰器被应用于类的构造函数,可以用来观察、修改或替换类定义
- 类装饰器不能用在声明文件中( .d.ts),也不能用在任何外部上下文中(比如declare的类)
- 类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数
- 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
function testDecorator(constructor: any) {
constructor.prototype.uname = "张三";
constructor.prototype.show = (): void => {
console.log(`我是${constructor.prototype.uname}`);
};
}
@testDecorator
class Person {}
let person = new Person();
// person.show(); 类型“Person”上不存在属性“show”
(person as any).show();
// 使用工厂函数
function testDecorator(flag: boolean) {
if (flag) {
return function (constructor: any) {
constructor.prototype.uname = "张三";
constructor.prototype.show = (): void => {
console.log(`我是${constructor.prototype.uname}`);
};
};
} else {
return function (constructor: any) {};
}
}
@testDecorator(true)
class Person {}
let person = new Person();
(person as any).show();
解决person as any 才能调用 show()的问题
// 函数可以接收很多的参数,参数类型都是any,将它们放在一个数组中
// T就相当于一个类,里面有构造函数
function testDecorator<T extends new (...args: any[]) => {}>(constructor: T) {
// 直接constructor做扩展
return class extends constructor {
name = "张三";
show() {
console.log(`我是${this.name}`);
}
};
}
@testDecorator
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
}
let person = new Person("李四");
(person as any).show(); // 我是张三
// 工厂模式
function testDecorator() {
return function <T extends new (...args: any[]) => {}>(constructor: T) {
// 直接constructor做扩展
return class extends constructor {
name = "张三";
show() {
console.log(`我是${this.name}`);
}
};
};
}
const Person = testDecorator()(
class {
name: string;
constructor(name: string) {
this.name = name;
}
}
);
let person = new Person("李四");
person.show(); // 我是张三
方法装饰器
- 方法装饰器写在在一个方法的声明之前
- 方法装饰器可以用来监视,修改或者替换方法定义。
- 方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
静态成员的类的构造函数,或者实例成员的类的原型
成员的名称
该成员的属性描述符
function getNameDecorator(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
console.log("target:", target);
console.log("key:", key);
console.log("descriptor:", descriptor);
/*
target: {}
key: getName
descriptor: {
value: [Function: getName],
writable: true,
enumerable: false,
configurable: true
}
*/
}
class Person {
name: string = "张三";
constructor(name: string) {
this.name = name;
}
@getNameDecorator
getName() {
return this.name;
}
}
let person = new Person("李四");
console.log(person.getName());
访问器的装饰器
访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。 访问器装饰器应用于访问器的 属性描述符并且可以用来监视,修改或替换一个访问器的定义。 访问器装饰器不能用在声明文件中(.d.ts),或者任何外部上下文(比如 declare的类)里。
方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名称。
- 该成员的属性描述符
TypeScript不允许同时装饰一个成员的get和set访问器。
function visitDecorator(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
console.log(target);
}
class Test {
private _name: string;
constructor(name: string) {
this._name = name;
}
get name() {
return this._name;
}
set name(newName: string) {
this._name = newName;
}
}
const t = new Test("张三");
console.log(t.name);
属性的修饰器
- 属性装饰器写在一个属性声明之前(紧靠着属性声明)
- 属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
对于静态属性来说就是当前的类, 对于实例属性来说就是当前实例
成员的名字
function nameDecorator(target: any, key: string): any {}
class Test {
@nameDecorator
name = "张三";
}
let test = new Test();
console.log(test.name);
参数装饰器
- 参数装饰器声明在一个参数声明之前(紧靠着参数声明)
- 参数装饰器应用于类构造函数或方法声明
- 数装饰器不能用在声明文件(.d.ts),重载或其它外部上下文(比如 declare的类)里
- 参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
对于静态成员来说是当前的类,对于实例成员是当前实例。
参数所在的方法名称。
参数在参数列表中的索引。
function paramDecorator(target: any, method: string, index: number) {
console.log(target, method, index);
}
class Test {
getInfo(name: string, @paramDecorator age: number) {
console.log(name, age);
}
}
const test = new Test();
test.getInfo("张三", 18);