10.装饰器

2020-02-20  本文已影响0人  我只会吃饭
装饰器:

装饰器是一种特殊类型的声明,它可以被附加到类声明, 方法、属性或参数上,可以修改类的行为
简单的说 装饰器是一个方法,可以注入一些特殊的功能到类、方法、属性参数上

装饰器的写法: 普通装饰器(不可参数)、和装饰器工厂(可传参)
常见装饰器:类装饰器、属性装饰器、方法装饰器、参数装饰器

类装饰器

用于类构造函数,可以动态修改、替换、监视类的定义,在类声明之前定义(紧靠类声明)

方式一: 普通装饰器
function decorator(tar:any) {
    console.log(tar); 
    tar.prototype.aname = 'animal';
    tar.prototype.eat = function () { // 动态注入的方法
        console.log('啥都吃')
    }
}

@decorator
class Animal {
    aname:string|undefined;
}


let animal:any = new Animal(); // 如果新增某个属性或者方法,需要将实例指定为any
console.log(animal.aname);
animal.eat();
方式二:装饰器工厂
function decoFactory(params:string) {

    return function (tar:any) {

        tar.prototype.aname = params;
        tar.prototype.eat =  function () {
            console.log(`${this.aname}喜欢吃盼盼法式小面包`);
        }
    }
}

@decoFactory('可乐')
class Dog  {}

let kele:any = new Dog();
kele.eat();
类装饰器-重载构造函数

类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数;
类装饰器返回一个值,它会使用提供的构造函数来替换类的声明;

function overLoad(tar:any) {

    return class extends tar {
        aname = '火锅';
        eat() {
            console.log(this.aname + '喜欢吃盼盼');
        }
    }
}

@overLoad // 方法和属性都需要映射(必写)
class Dog {
    aname:string;
    constructor () {
        this.aname = '可乐'
    }

    eat() {
        console.log(this.aname + '喜欢吃狗粮');
    }
    
}

let hg = new Dog();
hg.eat();
属性装饰器

属性装饰器会在运行时当做函数被调用,传入两个参数
1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2. 属性名

function propDecorator(params:string) {
    return function (target:any, prop:string) {
        console.log(target, 'target'); // 原型
        console.log(prop, 'props'); // 属性的名字
        target[prop] = params;
    }
}

class Person {
    @propDecorator('我是属性装饰器')
    fname:string|undefined
}

let person = new Person();
console.log(person.fname)
方法装饰器

用于方法的属性描述符上,可以监视修改替换方法的定义
方法修饰器接收三个参数: 原型对象、方法名字、方法的属性描述符

function methodDecorator(params:any) {
    return function (target:any, methodName:any, desc:any) {
        console.log(target);
        console.log(methodName);
        console.log(desc);

        // 原型对象添加属性
        target.fname = 'fname';
        // 原型对象添加方法
        target.eat = function () {
            console.log('我只会吃饭');
        }

        // 修改装饰器的方法
        let valFn = desc.value; // 为run 函数
        
        // 重新赋值
        desc.value = function (...argu:any[]) {

            // 重新指向原函数,且修改参数
            valFn.apply(this, argu.map(v => Number(v)));
        }
        
    }
}


class Person {
    @methodDecorator('a')
    // 方法装饰器,写在方法的前面
    run(...argus:any[]) {
        console.log(argus);
    }
}


let person = new Person();
console.log(person);
person.run(1, 2, 3, '4');
方法参数装饰器

可以添加一些数据

function paramsDecorator(params:string) {
    return function (target:any, methodName:string, paramsIndex: number) {
            console.log(params) ; // params
            console.log(target); // 原型对象
            console.log(methodName); // 方法名
            console.log(paramsIndex); // 参数下标

            target.fname = 'fname'; // 添加数据
    }
}

class Person {
    say(@paramsDecorator('我是参数') name:string) {

    }
}

let person = new Person();
上一篇下一篇

猜你喜欢

热点阅读