美文网首页
bunny学习笔记|TS的类装饰器/属性装饰器/方法装饰器

bunny学习笔记|TS的类装饰器/属性装饰器/方法装饰器

作者: 一只小小小bunny | 来源:发表于2022-06-20 11:22 被阅读0次

    装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为。通俗的装饰器就是一种方法,可以注入到类,方法,属性参数来扩展类,属性,方法,参数的功能。

    常见的装饰器有:类装饰器,属性装饰器,方法装饰器,参数装饰器;
    装饰器的写法:普通装饰器(无法传参),装饰器工厂(可传参)

    类装饰器

    类装饰器:装饰器在类声明之前被声明(紧跟着类声明)。类装饰器应用于类构造函数,可以用来监视,修改或者替换类定义,传入一个参数。

    (1)装饰器:(普通装饰器(无法传参))
    index.ts

    // 装饰器:(普通装饰器(无法传参))
    function logClass(params){
        console.log(params);//当前类
    //因此我们可以操作这个类
        params.prototype.apiUrl='动态扩展的属性';
        params.prototype.run=function(){
            console.log("我是一个run方法")
        }
    }
    
    @logClass
    class HttpClient{
        constructor(){}
        getData(){}
    }
    
    var http =new HttpClient();
    console.log(http.apiUrl);
    http.run();//用装饰器给类添加的方法
    

    PS:简单测试的话,可以新建对应的index.html文件,引入js,<script type="text/javascript" src="index.js"></script> ;另外要将ts转化为对应的index.js文件,终端执行法,tsc index.ts [前提是先安装tsc才可以执行]

    得到的结果:


    类装饰器

    (2) 类装饰器:装饰器工厂(可传参)
    index.ts

    function logClass(params:string){
    return function(target:any){
    //返回的target就是调用本装饰器的类
        console.log(target,"target");
        console.log(params,"params得到的值");
        target.prototype.apiUrl=params;//将传入的参数赋值给该类的原型扩展属性apiUrl
    }
    }
    
    @logClass('hello')//调用装饰器同时传入一个string类型的参数
    class HttpClient{
        constructor(){}
        getData(){}
    }
    
    var http =new HttpClient();
    console.log(http.apiUrl);
    
    输出的结果: 类装饰器

    (3)类装饰器重载构造函数
    类装饰器表达式会运行时当作函数被调用,类的构造函数作为其唯一的参数。如果类装饰器返回一个值,他会使用提供的构造函数来替换类的声明。

    function logClass(target:any){
        console.log(target,"target");
        return class extends target{
        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();
    
    输出结果: 类装饰器-重载构造函数

    属性装饰器

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

    index.ts

    //属性装饰器
    function logProperty(params:any){
        return function(target:any,attr:any){
            console.log(target,"target");
            console.log(attr,"attr");
            target[attr]=params;
        }
    }
    
    class HttpClient{
    
        @logProperty('http://www.baidu.com')
        public url:any|undefined
        constructor(){}
        getData(){
            console.log(this.url);
        }
    }
    
    var http:any =new HttpClient();
    http.getData();
    
    输出结果: 属性装饰器

    对应的index.js代码

    var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    //属性装饰器
    function logProperty(params) {
        return function (target, attr) {
            console.log(target, "target");
            console.log(attr, "attr");
            target[attr] = params;
        };
    }
    var HttpClient = /** @class */ (function () {
        function HttpClient() {
        }
        HttpClient.prototype.getData = function () {
            console.log(this.url);
        };
        __decorate([
            logProperty('http://www.baidu.com')
        ], HttpClient.prototype, "url");
        return HttpClient;
    }());
    var http = new HttpClient();
    http.getData();
    

    方法装饰器

    它会被应用带方法的属性描述符上,可以用来监听、修改、替换、方法定义

    方法装饰器运行时传入3个参数:
    (1)对于静态成员来说类的构造函数,对于实例成员来说是类的原型对象
    (2)成员的名字
    (3)成员的属性描述

    function logMethod(params:any){
        return function(target:any,methodName:any,desc:any){
            console.log(target,"--target--");
            console.log(methodName,"--methodName--");
            console.log(desc,"--desc--");
    
            target.apiUrl = params
            target.run = function(){
                console.log("--这是run--")
            }
        }
    }
    class HttpClient{
        public url:any | undefined;
        constructor(){}
        @logMethod('www.baidu.com')
        getData(){
            console.log(this.url,"--this.url--")
        }
    }
    var http:any = new HttpClient()
    console.log(http.apiUrl)
    http.run()
    
    输出结果: 方法装饰器
    使用方法装饰器修改方法
    function logMethod2(params:any){
        return function(target:any,methodName:any,desc:any){
            console.log(target); 
            console.log(methodName);
            console.log(desc);
            console.log(desc.value);
    
            // !!! 修改装饰器的方法,把装饰器所有传入的参数改为string
            // 1. 保存当前的方法
            var oMethod = desc.value;
            desc.value = function(...args:any[]){
                args = args.map((value)=>{ // map 循环遍历
                    return String(value) // 转类型
                })
                console.log(args) // [ 123, 999 ]
                oMethod.apply(this.args) // 用对象冒充来实现 把当前方法和参数传入
            }
        }
    }
    class HttpClient2{
        public url:any | undefined;
        constructor(){}
        @logMethod('www.baidu.com')
        getData(...args:any){ 
    // 将传入的any类型的参数解构
            console.log(args)
            console.log("我是getData里的方法")
            console.log(this.url)
        }
    }
    var http = new HttpClient2()
    http.getData(123,999)
    
    方法参数装饰器
    function logparams(params:any){
           return function(target:any,methodName:any,paramsIndex:any){
               console.log(params) // 传入的参数
               console.log(target) // 当前传入类的原型对象
               console.log(methodName) // 传入的方法名
               console.log(paramsIndex) // 索引值
               // 给这个参数添加传入的值
               target.apiUrl = params;
           }
       }
       class HttpClient3{
        public url:any | undefined;
        constructor(){}
        getData(@logparams('xxxx') uuid:any){
     // 在方法的参数里面调用装饰器,传入参数,在参数里还需要接收这个参数
            console.log("我是getData里的方法")
        }
    }
    var http = new HttpClient3()
    
    http.getData(123123);
    console.log(http.apiUrl) // xxxx
    

    学习源的链接:
    https://blog.csdn.net/weixin_40121676/article/details/105717756?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2

    相关文章

      网友评论

          本文标题:bunny学习笔记|TS的类装饰器/属性装饰器/方法装饰器

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