es7装饰器理解安装与使用(nestjs常用)

本文详细介绍了JavaScript中的装饰器,包括其定义、作用和设计思想。探讨了类装饰器、装饰器语法糖、装饰器叠加、装饰器工厂、方法装饰器、属性装饰器和参数装饰器等概念,并通过实例展示了如何实现统一发送消息、文字高亮、函数延迟执行和网络请求的装饰器。装饰器旨在不修改原有代码的基础上,提供面向切面编程的能力,增强代码的灵活性。
摘要由CSDN通过智能技术生成

定义

首先装饰器是一个函数,用于修改类和类方法、类属性的一种语法,主要应用到面向对象编程。

作用

用来装饰一些类,被装饰的类和函数,即可以拥有装饰器的功能,在保证原来的逻辑不被污染的情况下加入新功能,非常的方便。

设计思想

面向切面编程:指扩展功能不修改源代码,将功能代码从业务逻辑代码中分离出来。
开启装饰器语法支持:
在这里插入图片描述

类装饰器

// 定义装饰器
const moveDecorator: ClassDecorator = (target) => {
    // target就是我们的类(构造函数)
    // console.log(target);
    target.prototype.getPosition = () => {
        return {
            x: 100,
            y:200
        }
    }
}

// 在类上使用装饰器
@moveDecorator
class Tank { };

const t = new Tank();
console.log(t.getPosition()); // {x:100,y:200}

@moveDecorator
class Person { }
const p = new Person();
console.log(p.getPosition()); // {x:100,y:200}

类的语法糖

使用装饰器将类作为参数传入,给类的原型对象上追加属性

// 使用装饰器
@moveDecorator
class Tank { };
// ====
moveDecorator(Tank)

装饰器叠加

// 定义移动装饰器
const MoveDecorator: ClassDecorator = (target) => {
    // target就是我们的类(构造函数)
    // console.log(target);
    target.prototype.getPosition = () => {
        return {
            x: 100,
            y:200
        }
    }
}

// 定义播放音乐的装饰器
const MusicDecorator: ClassDecorator = (target: Function) => {
    target.prototype.playMusic = () => {
        console.log("播放音乐");
        
    }
    
}

// 叠加使用装饰器
@MoveDecorator
@MusicDecorator
class Tank { };
const t = new Tank();
console.log((<any>t).getPosition()); // {x:100,y:200}
(<any>t).playMusic(); // 播放音乐

装饰器工厂

给工厂函数传入不同的参数返回不同的装饰器

// 定义工厂装饰器
const MusicDecoratorFactory = (val: string): ClassDecorator => {
    if (val === "Tank") {
        return (target: Function) => {
            target.prototype.playMusic = (): void => {
                console.log(`播放${val}音乐`);
            }
        }
    } else {
        return (target: Function) => {
            target.prototype.playMusic = (): void => {
                console.log(`播放${val}音乐`);
            }
        }
    }    
}
// 使用装饰器工厂
@MusicDecoratorFactory("Tank")
class Tank { };
new Tank().playMusic();

@MusicDecoratorFactory("person")
class Person { }
new Person().playMusic();

方法装饰器

方法装饰器里面有三个参数

target:如果装饰器修饰的类方法,那么target代表原型对象,如果装饰器修改的是静态方法,那么target代表构造函数https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/static

const showDecorator: MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
    descriptor.value = (string?:string) => {
        console.log(`我的名字是${string}`);
    }
}

class User {
    // 使用方法装饰器
    @showDecorator
    public show() {
        console.log("coderyq");
    }
}

new User().show();

属性装饰器和参数装饰器

// 定义一个属性装饰器
const PropDecorator: PropertyDecorator = (target: Object, propertyKey: string | symbol) => {
    console.log(propertyKey); // name
}
// 定义参数装饰器
const ParamsDecorator: ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => {
    console.log(propertyKey, parameterIndex);  // show 2(代表参数的索引)
}
class User {
    @PropDecorator
    public name = "yq"
    public show(name: string, age: number, @ParamsDecorator des: string) {      
    }
}

例子

实现一个统一发送消息的装饰器
const MessageDecorator: ClassDecorator = (target: Function) => {
    target.prototype.message = (message:string) => {
          console.log(message);
    }
}
// 给登录的类
@MessageDecorator
class Login {
    public login() {
        console.log("处理业务");
    }
    
}
const t = new Login();
t.login();
t.message("登录成功");

实现文字高亮的方法装饰器

// 定义文字高亮装饰器
const HightTxtDecorator: MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
    // 将show方法赋值给method 
    const method = descriptor.value;
    // 改变原来的show方法·
    descriptor.value = () => {
        return `<div style="color:red">${method()}<div>`
    }
}
class User {
    // 使用方法装饰器
    @HightTxtDecorator
    public show() {
       return "coderyq"
    }
}
console.log(new User().show()); // <div style="color:red" > coderyq<div>

实现函数延迟执行的装饰器

// 定义函数延迟执行的装饰器工厂
const DelayFnDecoratorFactory = (time: number): MethodDecorator => {
    return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
        // 将show方法赋值给method 
        const method = descriptor.value;
        // 改变原来的show方法·
        descriptor.value = () => {
            setTimeout(() => {
                method();
            }, time)
        }
    }
}

class User {
    // 使用方法装饰器
    @DelayFnDecoratorFactory(3000)
    public show() {
      console.log('coderyq');
    }
}
new User().show();  // 3秒延迟打印

实现网络请求的装饰器

// 定义网络请求的装饰器
const RequestDecorator = (url: string): MethodDecorator => {
    return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
        // 模拟网络请求
        // axios.get(url)
        const method = descriptor.value;
        new Promise<number[]>(res => {
            setTimeout(() => {
                res([1]);
            },2000)
        }).then(res => {
            // 将结果通过参数传入到原函数里面
            method(res) // 结果: 1
        })
        
    }
}
class User {
    @RequestDecorator("https://interface.coderyq.cn")
    public all(res: any[]) {
        console.log("结果:" + res); 
    }
}
属性装饰器动态改变字母大小写

关于defineProperty的详细用法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty


// 定义一个属性装饰器
const LowerDecorator: PropertyDecorator = (target: Object, propertyKey: string | symbol) => {
    let value: string;
    Object.defineProperty(target, propertyKey, {
        
        // 属性读取的时候自动调用
        get() {
            return value.toUpperCase();
        },
        // 属性赋值的时候调用
        set(v) {
            value = v;
        }
    })
}


class User {
    @LowerDecorator
    public name:string | undefined
}

const t = new User();
t.name = 'codeDWDDSryqsdsadasdasd';
console.log(t.name);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值