`

TypeScript语法基础 - 装饰器

阅读更多

装饰器: 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或者参数上,可以修改类的行为。

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

常见的装饰器有: 类装饰器,属性装饰器,方法装饰器,参数装饰器

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

类装饰器

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

装饰器的执行顺序

属性>方法>方法参数>类 如果有多个同样的装饰器,它会优先执行后面的(从里到外的执行顺序)

 

   1. 类装饰器

a. 普通装饰器(无法传参)

 

function logClass(params:any) {
    //params就是当前类
    console.log(params)// [Function: HttpClient]
    params.prototype.apiUrl='动态扩展属性';
    //扩展动态方法
    params.prototype.run=function(){
        console.log('我是一个run方法');
    }
}

//调用装饰器用@ 普通装饰器无法传参
@logClass
class HttpClient{
    constructor() {}
    getData(){}
}

var http:any=new HttpClient();
console.log(http.apiUrl);//动态扩展属性
http.run();//我是一个run方法

 

 

 

b.装饰器工厂(可传参)

 

function logClass(params:string) {
    return function(target:any){
        console.log(target);//把类 传参给
        target.prototype.apiUrl=params;
    }
}

//调用装饰器用@
@logClass('www.baidu.com')
class HttpClient{
    constructor() {}
    getData(){}
}
var http:any=new HttpClient();
console.log(http.apiUrl);

 

 

c. 类装饰器 重载构造函数的例子

 

/*
类构造器表达式会在运行时当做函数被调用,类的沟站函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
* */

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 http=new HttpClient();
http.getData();//我是修改后的数据----

 

 

 

   2. 属性装饰器

/*
属性装饰器表达式会在运行时,当做函数被调用,传入下列两个参数
对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
成员的名字
**/
function logProperty(params:any){
    return function(target:any,attr:any){
        console.log(target) //HttpClient { getData: [Function] }
        console.log(attr) //apiUrl
        target[attr]=params;

    }

}

@logClass('xxxxx')
class HttpClient{
    @logProperty('xxxsssss')
    public apiUrl:string | undefined;
    constructor() {}

    getData(){
        console.log(this.apiUrl)//xxxsssss
    }
}
var http=new HttpClient();
http.getData();//我是修改后的数据----

   3. 方法装饰器

/*
方法装饰器 它会接应应用到方法的属性的描述符上,可以用来监视,修改或者替换方法的定义
方法的装饰会在运行时传入下列3个参数
1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2.成员的名字
3.成员的属性描述符
*/
function logMethod(params:any){
    return function (target:any,methodName:any,desc:any) {
        console.log(target); //HttpClient { getData: [Function] }
        console.log(methodName); //getData
        console.log(desc); // { value: [Function],writable: true, enumerable: true,configurable: true }
        target.apiUrl='mssmmsmsm';
        target.run=function () {
            console.log('run')
        }
    }
}

class HttpClient{
    public url:any | undefined;
    constructor() {}
    @logMethod('xxxx')
    getData(){
        console.log(this.url);
    }
}
var http:any=new HttpClient();
console.log(http.apiUrl);
http.run();

//方法装饰器 修改getData方法
function logMethod(params: any) {
    console.log(params)
    return function (target: any, methodName: any, desc: any) {
        console.log(target); //HttpClient { getData: [Function] }
        console.log(methodName); //getData
        console.log(desc.value); //方法定义
        //修改装饰器的方法,把装饰器方法里面传入的所有参赛改为string类型
        //保存当前的方法
        var oMethods=desc.value;
        //替换
        desc.value=function (...args:any[]) {
            args=args.map((value)=>{
                return String(value)
            })
            console.log(args);
            //修改方法 对象冒充
            oMethods.apply(this,args);
        }
    }
}

class HttpClient {
    public url: any | undefined;
    constructor() {}
    @logMethod('xxxx')
    getData(...args:any[]) {
        console.log(args)
        console.log('我是getData中的方法');
    }
}
var http: any = new HttpClient();
http.getData('123','xxx');//[ '123', 'xxx' ]

   4. 参数装饰器

/*
方法参数装饰器
参数装饰器表达式会在运行时当做函数直接调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数
对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
参数的名字
参数在函数参数列表的索引。
**/
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 HttpClient {
    public url: any | undefined;
    constructor() {}
    
    getData(@logParams('uuiddddddddd') uuid: any) {
        console.log('我是getData里面的方法')
        console.log(uuid+'----');
    }
}
//实例化
var http:any = new HttpClient();
http.getData(11111)
console.log(http.apiUrl);

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics