美文网首页
ES7 decorator详解。

ES7 decorator详解。

作者: TouchMe丶 | 来源:发表于2019-06-24 10:15 被阅读0次

    装饰器

    概念

    装饰器是一种特殊类型的声明,他能够被附加到类声明,方法,属性或者参数上。可以修改类的行为。常见的装饰器有:类装饰器,属性装饰器,方法装饰器。装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参).

    类装饰器

    类装饰器在类声明之前被声明。类装饰器应用于类构造函数,可以用来监视,修改或替换定义。传入一个参数,代表当前类。装饰器可以在不修改类的前提下来扩展类的功能:

    //普通装饰器
    function logClass(params:any){
       //普通装饰器的参数params代表的被装饰器修饰的类
       //扩展params的属性和方法
        params.prototype.xxx = "xxxxxx";
        params.prototype.run = function(){
          console.log("我是一个run方法");
        }
    }
    
    @logClass
    class Aclass{
      constructor(){}
      getData(){}
    }
    
    //查看效果
    var A = new Aclass();
    A.run();
    

    在控制台中,上面会输出"我是一个run方法"的字符串。说明我们的装饰器编写成功了。
    下面我们来构建一个可以传参的类装饰器,被称为装饰器工厂。这种装饰器的具体写法就是在装饰器函数内返回一个新的函数,新函数有一个参数target,代表被修饰的类,而上层函数的参数params,则代表了传入的参数。

    function logClass(params:string){
      return function(target:any){
        console.log(target);//代表目标类HttpClient
        console.log(params);//代表装饰器工厂传的参数 "hello"
        target.prototype.apiUrl = params;
      }
    }
    
    @logClass("http://www.baidu.com")
    class HttpClient{
      constructor(){}
      getData(){}
    }
    
    var http = new HttpClient();
    console.log(http.apiUrl);
    

    上面的代码会在控制台打印出"http://www.baidu.com".
    接下来,再看另一种情况。修改当前类的构造函数的装饰器。类装饰器表达式会在运行时当做函数被调用,类的构造函数作为其唯一的参数。如果类装饰器返回一个值,它会使用提供的构造函数类替换类的声明。

    function logClass(target:any){
      console.log(target);
      return class extends target{ //target就是下面的httpClient这个类
        apiUrl:any = "我是修改后的数据";
        getData(){
          this.apiUrl = this.apiUrl + "---";
          console.log(this.apiUrl);
        }
      } 
    }
    
    @logClass
    class httpClient{
      public apiUrl:string | undefined;
      constructor(){
        this.apiUrl = "我是构造函数里面的apiUrl";
      }
      getData(){
        console.log(this.apiUrl);
      }
    }
    //查看效果
    var http = new httpClient();
    http.getData();
    

    属性装饰器

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

    //类装饰器
    function logClass(params:any){
      return function(target:any){
        // console.log(target);//类
        // console.log(params);//参数
      }
    }
    //属性装饰器
    function logProperty(params:any){
      console.log(params);
      return function(target:any,attr:any){
        //target对静态成员来说是类的构造函数,对于实例成员是类的原型对象
        console.log(target);
        console.log(attr);
        target[attr] = "hahaha";//修改了下面的url  
      }
    }
    
    @logClass("xxxx")
    class httpClient{
      @logProperty("http://ityinglcn")//装饰下面那个属性url
      public url:string | undefined;
      constructor(){
    
      }
      getData(){
        console.log(this.url);
      }
    }
    
    var http = new httpClient();
    http.getData();
    

    方法装饰器

    方法装饰器会被应用到方法的属性描述符上 可以用来监视,修改或者替换方法定义。
    方法装饰器会在运行时传入下列3个参数:
    1.对静态成员来说是类的构造函数,对实例成员来说是类的原型对象。
    2.成员的名字。
    3.成员的属性描述符。

    //扩展当前类HttpClient的实例和方法。
    function get(params:any){
      return function(target:any,name:any,desc:any){//target这个例子代表了HttpClient类
        //扩展当前类HttpClient的实例和方法。
        target.apiUrl = "xxx";
        target.run = function(val:string){
          console.log('run')
        }
      }
    }
    class HttpClient{
      public url:any | undefined;
      constructor(){
    
      }
      @get("http://www.itying.com")
      getData(){ //这个getData是实例方法 所以拿到的是HttpClient的原型对象
        console.log(this.url);
      }
    }
    var http:any = new HttpClient();
    console.log(http.apiUrl);
    http.run();
    

    修改被修饰的方法。

    function get(params:any){
      return function(target:any,name:any,desc:any){//target这个例子代表了HttpClient类
        //修改getData()方法  就要修改desc下面的value 这个value就是被修饰的方法
        // console.log(desc.value);
        //把getData传入的参数改为string类型
    
        //1.保存当前的方法
        var oMethod = desc.value;
        //2.修改
        desc.value = function(...args:any[]){
          args = args.map(item => {
            return item.toString();
          });
          console.log(args);
          //如果只是修改  不替换  就用下面的方法 在里面调用oMethod 并且把参数args传入
          oMethod.apply(this,args);
        };
      }
    }
    class HttpClient{
      public url:any | undefined;
      constructor(){
    
      }
      @get("http://www.itying.com")
      getData(...args:any[]){ //这个getData是实例方法 所以拿到的是HttpClient的原型对象
        console.log(args);
        console.log("我是getData里面的方法");
      }
    }
    
    var http:any = new HttpClient();
    http.getData(123,"xxx"); 
    

    相关文章

      网友评论

          本文标题:ES7 decorator详解。

          本文链接:https://www.haomeiwen.com/subject/tncnqctx.html