NO10 Typescript 中的装饰器

157 阅读3分钟

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

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

// 普通装饰器 类装饰器: 用来监视、修改、替换类定义

function logClass(params: any) { // params就是当前类

    console.log(params)

    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()

// 装饰器工厂(可传参) 类装饰器

function logClass(params: string) { 

    return function (target:any) {

        console.log(target) // 当前类

        console.log(params) // www.baidu.com

        target.prototype.apiUrl = params

    }

}

@logClass('www.baidu.com')

class HttpClient{

    constructor() {

    }

    getData() {

    }

}

var http:any = new HttpClient()

console.log(http.apiUrl)
/**

 *  例子: 重载构造函数

 * 类装饰器: 会在运行时当做函数被调用,类的构造函数作为其唯一的参数

 * 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明

 */


function logClass(target:any) { 

    console.log(target) // 当前类

    return class extends target {

        apiUrl:string = '我是修改后的数据'

        getData() {

            console.log(this.apiUrl + '000000')

        }

    }

}

@logClass

class HttpClient{

    apiUrlstring 

    constructor() {

        this.apiUrl = '我是构造函数里面的apiUrl'

    }

    getData() {

        console.log(this.apiUrl)

    }

}

var http:any = new HttpClient()

http.getData()

/**

 * 属性装饰器

 */

function logClass(params:any) { 

    return function(target:any) {

        console.log('类装饰器' + params)

        console.log('类装饰器' + target)

    }

}

function logProperty(params:any) {

    return function(target:any, attr: any) {

        console.log('属性装饰器' + params)

        console.log(target) // 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象

        console.log('属性装饰器' + attr) // 属性的名字

        target[attr]= params

    }

}

@logClass('xxx')

class HttpClient{

    @logProperty('www.google.com')

    public apiUrlstring | undefined

    constructor() {

    }

    getData() {

        console.log(this.apiUrl)

    }

}

var http:any = new HttpClient()

console.log(http)

http.getData()

/**

 * 方法装饰器 用来监视、修改、替换方法的定义

 */

function logMethod(params:any) {

    return function (target:any, methodName: string, desc: any) {

        console.log(target) // 对于静态成员是类的构造函数,对于实例成员是类的原型对象

        console.log(methodName) // 方法名字

        console.log(desc) // 对方法的描述


        target.name = 'xxx'

        target.run = function () {

            console.log('run')

        }

        // 替换getData方法,把修饰器方法里面传入的参数改为string类型

        // desc.value = function(...args:any[]) {

        //     args = args.map(v => String(v))

        //     console.log(args)

        // }

        // 修改方法

        var oMethod = desc.value

        desc.value = function(...args:any[]) {

            args = args.map(v => String(v))

            console.log(args)

            oMethod.apply(this, args)

        }

    }

}

class HttpClient{ 

    public apiUrl: string | undefined

    constructor() {

    }

    @logMethod('xxxxx'// 把传入的参数变成string类型

    getData(...args:any[]) {

        console.log(args)

        console.log('我是getData中的方法')

    }

}

var http:any = new HttpClient()

// http.run()

http.getData('haha'123)


/**

 * 方法参数装饰器

 */

function logParams(params:any) {

    return function (target: any, methodName: any, paramsIndex: any) {

        console.log(params)

        console.log(target) // 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象

        console.log(methodName) // 方法的名字

        console.log(paramsIndex) // 参数在函数参数列表中的索引

    }

}

class HttpClient{ 

    public apiUrl: string | undefined

    constructor() {

    }

    getData(@logParams('xxxx') uuid:any) {

        console.log(uuid)

    }

}

var http = new HttpClient()

http.getData(1)


/**

 * 装饰器执行的顺序

 */

function logClass1() {

    return function() {

        console.log('类装饰器1');        

    }

}

function logClass2() {

    return function() {

        console.log('类装饰器3');        

    }

}

function logAttribute() {

    return function(target: any, attrName: any,) {

        console.log('属性装饰器');        

    }

}

function logMethod() {

    return function(target: any, attrName: any, desc: any  ) {

        console.log('方法装饰器');        

    }

}

function logParams1(params:any) {

    return function (target: any, methodName: any, paramsIndex: any) {

        console.log('方法参数装饰器1');        

    }

}

function logParams2(params:any) {

    return function (target: any, methodName: any, paramsIndex: any) {

        console.log('方法参数装饰器2');        

    }

}

@logClass1('aaa')

@logClass2('bbb')

class HttpClient{ 

    @logAttribute()

    public apiUrl: string | undefined

    constructor() {

    }

    @logMethod()

    getData(@logParams1('xxxx') attr:any, @logParams2() uuid:any) {

        console.log(uuid)

    }

}

var http = new HttpClient()

http.getData('kkkk','kjkkjlklk')