typescript的装饰器使用

原创
2018/05/08 10:03
阅读数 1.3K
//不带参数的装饰器
function logClass(target: any) {
    var original = target;
    function construct(constructor, args) {
        var c: any = function () {
            return constructor.apply(this.args);   
        }
        c.prototype = constructor.prototype;
        return new c();
    }
    var f: any = function (...args) {
        console.log("New:" + original.name);
        return construct(original, args);
    }
    f.prototype = original.prototype;
    return f;
}
//类装饰器,带有参数的
function logClass2(option:string) {
    return function (target: any) {
        console.log("option:"+option);
        var original = target;
        function construct(constructor, args) {
            var c: any = function () {
                return constructor.apply(this.args);   
            }
            c.prototype = constructor.prototype;
            return new c();
        }
        var f: any = function (...args) {
            console.log("New:" + original.name);
            return construct(original, args);
        }
        f.prototype = original.prototype;
        return f; 
    }
}
//方法装饰器
function logMethod(target: any, key: string, descriptor: any) {
    var originalMethod = descriptor.value;//保留原方法的引用
    descriptor.value = function (...args: any[]) {
        var a = args.map(a => JSON.stringify(a)).join();//将方法参数转为字符串
        var result = originalMethod.apply(this, args);//执行方法,得到其返回值
        var r = JSON.stringify(result);//将返回值转为字符串
        console.log(`Call:${key}(${a}) => ${r}`);
        return result;
    }
    return descriptor;//返回编辑后的属性描述对象
}
//属性装饰器
function logProperty(target: any,key:string) {
    var _val = this[key];//属性值
    var getter = function () {
        console.log(`Get:${key} => ${_val}`);
        return _val;
    }
    var setter = function (newVal) {
        console.log(`Set:${key} => ${newVal}`);
        _val = newVal;
    }
    //删除属性,在严格模式下,如果对象是不可配置的,将会抛出一个错误。否则返回false
    if (delete this[key]) {
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable:true
        })
    }
}
//参数装饰器
function addMetadata(target: any, key: string, index: number){
    var metadataKey = `_log_${key}_parameters`;
    if (Array.isArray(target[metadataKey])) {
        target[metadataKey].push(index);
    } else {
        target[metadataKey] = [index];
    }
}
//读取通过参数装饰器添加的元数据,在执行时,不在展示所有参数,而是仅打印被装饰的参数
function readMetadata(target: any, key: string, descriptor: any) {
    var originMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
        var metadataKey = `_log_${key}_parameters`;
        var indices = target[metadataKey];
        if (Array.isArray(indices)) {
            for (var i = 0; i < args.length; i++){
                if (indices.indexOf(i) !== -1) {
                    var arg = args[i];
                    var argStr = JSON.stringify(arg) || arg.toString();
                    console.log(`${key} arg[${i}]:${argStr}`);
                }
            }
            var result = originMethod.apply(this, args);
            return result;
        }
        return descriptor;
    }
}
@logClass
@logClass2("option value")
class Person {
    public name: string;
    @logProperty
    public surname: string;
    constructor(name: string, surname: string){
        this.name = name;
        this.surname = surname;
    }
    @readMetadata
    @logMethod
    say(@addMetadata st:string):string {
        console.log(this.name + "-->" + this.surname + " says :"+st);
        return this.name + "-->" + this.surname + " says :"+st;
    }
}
var me = new Person("raa", "jan");
me.surname = "hello1";
var n = me.surname;
me.say("hello");

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部