ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TypeScript学习: 十二、TS中的装饰器

2022-01-19 23:35:35  阅读:229  来源: 互联网

标签:TypeScript console log TS 十二 装饰 params 参数 any


前言

装饰器: 装饰器是一种特殊类型声明, 它能够被附加到类声明,方法,属性或者参数上, 可以修改类的行为 通俗的讲装饰器就是一个方法, 可以注入到类,方法,属性参数上来扩展类,属性,方法,参数功能 常见的装饰器:属性装饰器,方法装饰器,参数装饰器 写法: 普通修饰器(无法传参)、装饰器工厂(可以传参)  

类修饰器

装饰器在类声明之前被执行,类装饰器应用于类构造函数,可以用来监视,修改或者代替类定义  

类普通装饰器:

function logClass(params: any) { 
    console.log(params); 
}


@logClass
class HttpClient{
    constructor() {

    }
    getData() {

    }
 }

 定义了一个 logClass 类   并且带了一个默认参数  params

这个 params == HttpClinent   

function logClass(params: any) {
    console.log(params); 
    params.prototype.httpUrl = "http.xxxxx"; // 通过原型链添加一个 给类添加一个属性
}


@logClass
class HttpClient{
    constructor() {

    }
    getData() {

    }
 }

var httpClient = new HttpClient();
console.log(httpClient.httpUrl);

运行结果:

 

 通过 类装饰器添加 方法

function logClass(params: any) {
    console.log(params); 
    params.prototype.httpUrl = "http.xxxxx"; // 通过原型链添加一个 给类添加一个属性

    params.prototype.run = function() {
        console.log("run-app");
    }
}

@logClass
class HttpClient{
    constructor() { }
    getData() { }
 }

var httpClient = new HttpClient();
console.log(httpClient.httpUrl);
httpClient.run(); // 执行通过装饰器添加的方法

 

 类装饰器工厂:

function logClass(params: string) {
    console.log(params); // 传入的参数类型
   return function(tarage:any) { 
        // tarage == HttpClient
   }
}

@logClass("传入参数")
class HttpClient{
    constructor() { }
    getData() { }
}

var httpClient = new HttpClient();

 

 如果是装饰器工厂必须要写入 参数     @logClass("传入参数")    

可以根据装饰器传入的参数去实现需要的功能

function logClass(params: string) {
    console.log(params); // 传入的参数类型
   return function(tarage:any) { 
        // tarage == HttpClient
        tarage.prototype.apiUrl = params; // 通过原型链修改 类的属性
   }
}

@logClass("http://xxxxxx123")
class HttpClient{
    constructor() { }
    getData() { }
}

var httpClient = new HttpClient();

 

而且还可以重载 构造函数
function logClass(target: any) {
    console.log(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 httpClient = new HttpClient();
console.log(httpClient.apiUrl)
httpClient.getData();

 属性装饰器

 属性装饰器表达式会在运行时当作函数调用, 传入2个参数  * 第一个参数:对于静态成员来说 是类的构造函数, 对于实例化成员是类的原型对象  * 第二个参数:成员名字
function logProperty(params: any) {
    console.log("接收传入的参数", params);
    return function(tarage: any, attr: any) {
        console.log("参数一:", tarage); // 对于实例化成员是类的原型对象
        console.log("参数二:", attr);// 成员名字
    }
}

class HttpClient{
    
    @logProperty("test")
    public url:string|undefined; // 这个属性使用 属性装饰器
    
    constructor() {   }
    getData() {  }
}

 通过参数一   修改属性值:

function logProperty(params: any) {
    console.log("接收传入的参数", params);
    return function(tarage: any, attr: any) {
        console.log("参数一:", tarage); // 对于实例化成员是类的原型对象
        console.log("参数二:", attr);// 成员名字
        tarage[attr] = params; // 这里修改属性值
    }
}

class HttpClient{
    
    @logProperty("test")
    public url:string|undefined; // 这个属性使用 属性装饰器
    
    constructor() {   }
    getData() { 
        console.log( "url属性值", this.url);
     }
}

var httpClient = new HttpClient();
httpClient.getData(); // 输出     url属性值 test

方法装饰器

它会被应用到方法的 属性描述符上, 可以用来监视,修改或者替换方法定义    * 方法装饰器会在运行时传入3个参数  *  参数一: 对于静态成员来说是类的构造函数,对于实例成员是类的原型  *  参数二: 成员名字  *  参数三: 成员的属性描述符。
function logMethod(params:any) {
    console.log("调用传入的参数", params)
    return function(tarage:any, methodName: string, desc:any){
        console.log("参数一", tarage); // 实例成员是类的原型
        console.log("参数二", methodName); // 成员名字, 方法名
        console.log("参数三", desc); // 描述
    }
}



class HttpClient{
    
    public url:string|undefined;
    
    constructor() {   }

    @logMethod("get")
    getData() { // 这个方法使用了 装饰器
        console.log( "url属性值", this.url);
     }
}

 第一个参数是 实例成员的原型, 可以通过它给原型添加属性或方法

function logMethod(params:any) {
    console.log("调用传入的参数", params)
    return function(tarage:any, methodName: string, desc:any){
        console.log("参数一", tarage); // 实例成员是类的原型
        console.log("参数二", methodName); // 成员名字, 方法名
        console.log("参数三", desc); // 描述

        tarage.api = "我是装饰器添加的 属性";
        tarage.run = function() {
            console.log("我是装饰器添加的方法");
        }
    }
}



class HttpClient{
    
    public url:string|undefined;
    
    constructor() {   }

    @logMethod("get")
    getData() { // 这个方法使用了 装饰器
        console.log( "url属性值", this.url);
     }
}

var httpClient = new HttpClient();
console.log(httpClient.api); // 输出: 我是装饰器添加的 属性
httpClient.run();  // 输出 我是装饰器添加的方法

 

第三个参数是 描述    
修改装饰器方法, 把装饰器方法里面的所有参数修改为string类型
function logMethod(params:any) {
    console.log("调用传入的参数", params)
    return function(tarage:any, methodName: string, desc:any){
       
       console.log(desc.value); // 输出 function() { console.log( "url属性值", this.url);}
       var methodFun = desc.value;
       desc.value = function(...args:any) { // 重写 getData 方法
            args = args.map((value:any)=>{
                return String(value);
            });
            console.log(args);

            // 使用对象冒充, 还原之前的函数
            methodFun.apply(this, args); // 执行输出 我是getData方法
       }
    }
}

class HttpClient{
    
    public url:string|undefined;
    
    constructor() {   }

    @logMethod("get")
    getData(...args:any) { // 这个方法使用了 装饰器
        console.log(args);// 输出: Array(2) ["123", "adb"]
        console.log( "我是getData方法");
     }
}

var httpclient = new HttpClient();
httpclient.getData(123, "adb");  // 输出: Array(2) ["123", "adb"]

 

方法参数装饰器

参数装饰器表达式会在运行时当作函数调用,可以使用参数装饰器为类的原型 增加一些元素数据,传入三个参数:
参数一: 对于静态成员来说是类的构造函数, 对于实例成员是类的原型对象 参数二:方法名称 参数三:参数在函数参数列表中的索引
function logParams(params:any) {
    return function(target:any,methodName:any,paramsIndex:number){
        console.log(params);// 我是装饰器参数
        console.log(target); // Object {getData: , constructor: }
        console.log(methodName); // getData
        console.log(paramsIndex);// 0
    }
}

class HttpClient{
    public url:string|undefined;
    constructor() {   }

    getData(@logParams("我是装饰器参数")uuid:any) { // 这个方法使用了 装饰器
        console.log(uuid);
        console.log( "我是getData方法");
     }
}

var httpClinet = new HttpClient();
httpClinet.getData("test");

 

 注意装饰器的执行顺序:

属性装饰器>方法装饰器>方法参数装饰器>类装饰器

如果一个方法有两个装饰器, 那么 后面的装饰器先执行,再到前面的

标签:TypeScript,console,log,TS,十二,装饰,params,参数,any
来源: https://www.cnblogs.com/yangWanSheng/p/15820438.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有