- List item 是一种特殊类型的申明,它能够被附加到类申明、方法、属性或参数上,可以修改类的行为
- 通俗的讲,装饰器就是一个方法,可以注入到类、方法、属性或参数上来扩展类、属性、方法、参数的功能
- 常见的装饰器: 类装饰器、属性装饰器、方法装饰器、参数装饰器
- 装饰器的写法: 普通装饰器(无法传参)、装饰器工厂(可以传参)
类装饰器
-
普通类装饰器
普通装饰器中的参数只有一个,就是当前类,不能传参
function createDecor(params:any) {
console.log(params); // 就是当前类
params.prototype.newAttr = '动态给类添加属性';
params.prototype.fn = function():void{
console.log('动态给类添加方法')
}
}
@createDecor // 注意在用装饰器的时候,这里不能加分号
class CreateClass{
constructor() {}
getName() {
console.log('这个类本来的方法')
}
}
const decor:any = new CreateClass();
decor.getName();
console.log(decor.newAttr);
decor.fn();
- 装饰器工厂
function createDecor(params: string) { // 定义装饰器
console.log(params) // 这个参数就是装饰器传递的参数
return function(target:any) {
console.log(target) // 这个target就是CreateClass这个类
target.prototype.getInfo = function () {
console.log('动态创建的方法', params);
}
}
}
@createDecor('传递的参数')
class CreateClass{
constructor(){}
getName() {
console.log('类内部的方法')
}
}
const decor:any = new CreateClass();
decor.getInfo()
- 类装饰器修改类中的构造函数和方法
function decorObj(param:any) {
console.log(param) // param就是createObj这个类
return class extends param{
name:any = '我是修改后的名字';
getName() {
console.log(this.name + '222222')
}
}
}
@decorObj
class createObj {
public name:string | undefined;
constructor(name:string) {
this.name = name;
}
getName() {
console.log(this.name)
}
}
const obj = new createObj('张山');
obj.getName(); // 打印 我是修改后的名字222222
// 通过这个打印结构告诉我们,createObj的构造函数和getname这个方法都被修改了
- 属性装饰器
下面的参数target: 对于静态方法来说是类的构造函数,对于实例成员来说是原型对象prototype
function decorAttr(params:string) {
console.log(params, 11);
return function (target:any, attr:string) {
console.log(target) // 注意这里target是CreateClass的prototype
console.log(attr) // attr就是name
// 注意上面的name是在构造函数中初始化的,这里实在属性装饰器中初始化的
target[attr] = params
}
}
class CreateClass {
@decorAttr('通过属性属性装饰器给name初始化')
public name:string | undefined;
constructor(){}
getName() {
console.log(this.name);
}
}
const obj = new CreateClass();
obj.getName()
- 方法装饰器
注意几点:
1、方法装饰器修改类中的某个方法的时候,在该方法前面加一个装饰器,如果要修改多个,那就要加多个装饰器
2、方法装饰器修改原来的方法的时候,相当于重新给方法名字重新赋值,如果还要保留原来的方法,那就需要在修改后的方法中执行原来的方法
function getMethods(params:string) {
// console.log(params);
return function(p1:any, p2:any, p3:any) {
// console.log(p1) // 参数一:对于静态方法来说是类的构造函数,对于实例成员来说是原型对象prototype
// console.log(p2) // 参数二:成员的名字
// console.log(p3) // 参数三:成员的描述信息
let modifyMethods = p3.value; // p3.value就是createMethods中的modifyData这个方法
p3.value = function (...args:any[]) { // 改写createMethods中的modifyData这个方法
args = args.map(item => String(item)) // 强制将modifyData方法中的参数转换为string类型
console.log(args)
modifyMethods.apply(this, args) // 相当于在修改后的方法中又执行了原本的modifyData这个方法
}
}
}
class createMethods{
public name:string | undefined
constructor() {}
@getMethods('123')
modifyData(...args:any[]) { // 修改方法的时候,就在那个方法前面加一个装饰器
console.log(args,'哈哈哈')
}
// @getMethods('456')
getName() {
console.log('111')
}
}
const me = new createMethods();
me.modifyData('456',45454)