typescript 装饰器

装饰器:就是一个方法,可以注入到类,方法,属性参数上来扩展类,方法,参数的功能

装饰器写法:普通装饰器(无法传参)、装饰器工厂(可传参)

类装饰器  在类声明之前被声明(紧靠类声明)。应用于类构造函数,可以用来监视,修改或替换类定义。 

普通装饰器

 

function logClass(params:any){
    console.log(params);  //params 即为 HttpClient类
    params.prototype.apiUrl = 'xxx';
}
// 用@+装饰器名称来表示
@logClass 
class HttpClient {

}
var h:any = new HttpClient();
console.log(h.apiUrl); //xxx

 

装饰器工程

function logClass(params:string){
    console.log(params);  //params 即为装饰器传入的参数
    return function(target:any){ //target为 HttpClient类
        target.prototype.apiUrl = params;
    }
}
// 用@来表示
@logClass('hello') 
class HttpClient {

}
var h:any = new HttpClient();
console.log(h.apiUrl); //hello

类装饰器重载构造函数以及方法

function logClass(params:any){

    return class extends params{
        apiUrl:string = '我是修改后的';
        getData(){
            this.apiUrl = this.apiUrl + '.....';
            console.log(this.apiUrl);
        }
    }
}
// 用@来表示
@logClass
class HttpClient {
    apiUrl:string | undefined
    constructor(){
        this.apiUrl = '我在构造函数里';
    }
    getData(){
        console.log(this.apiUrl);
    }
}
var h:any = new HttpClient();
h.getData();  //我是修改后的......

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

function logAttr(params:any){ //param 属性修饰器传入的参数
    return function(target:any,attr:any){ //target 类的实例 attr 属性名
        console.log(target)
        console.log(attr)
        target[attr] = params;
    }
}

class HttpClient {
    @logAttr('属性装饰器。。。')
    apiUrl:string | undefined
    constructor(){

    }
    getData(){
        console.log(this.apiUrl);
    }
}
var h:any = new HttpClient();
h.getData(); //属性装饰器。。。

方法装饰器  应用到方法的属性描述上,可用来监视修改或者替换方法定义

  运行时传入下列3个参数

  1.对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象

  2.成员的名字

  3.成员的属性描述符

 

//扩展属性和方法
function get(params:any){ //param 属性修饰器传入的参数
    return function(target:any,methodName:any,describe:any){ //target 类的实例 attr 属性名
        console.log(target)
        console.log(methodName);
        console.log(describe.value)
        target.url = 'xxxxx';
        target.run = function(){
            console.log('run');
        }
    }
}

class HttpClient {
    apiUrl:string | undefined
    constructor(){

    }
    @get("www.baibai.com")
    getData(){
        console.log('getData方法里');
    }
}
var h:any = new HttpClient();
console.log(h.url);
h.run();

 

//修改当前的方法
function get(params:any){ //param 属性修饰器传入的参数
    return function(target:any,methodName:any,describe:any){ //target 类的实例 attr 属性名
        console.log(target)
        console.log(methodName);
        console.log(describe.value)
        let oMethod = describe.value;
        describe.value = function(...args:any[]){
            args = args.map((value)=>{
                return String(value)
            })

            console.log(args);

            oMethod.apply(this,args);
        }
    }
}

class HttpClient {
    apiUrl:string | undefined
    constructor(){

    }
    @get("www.baibai.com")
    getData(...args:any[]){
        console.log('getData方法里');
    }
}
var h:any = new HttpClient();
h.getData(12,'xxx');

方法参数装饰器  (不常用)

参数装饰器表达式会在运行时当做函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数

1.对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象

2方法的名字

3.参数在函数参数列表中的索引

function logParams(params:any){
    return function(target:any,methodName:any,paramsIndex:any){
        target.url = params;
    }
}

class HttpClient {
    apiUrl:string | undefined
    constructor(){

    }
    getData(@logParams('xxx') uuid:any){
        console.log('getData方法里');
    }
}
var h:any = new HttpClient();
console.log(h.url)

四种装饰器执行顺序

属性 -->  方法 -->  方法参数(从后向前执行 2 -> 1 )--> 类装饰器 (从后向前 2 -> 1)

 

posted @ 2020-04-14 17:49  砂糖一椰子  阅读(519)  评论(0编辑  收藏  举报