Typescript学习笔记 - 装饰器 @(类,属性,方法)

普通装饰器 (无法传参)

// 类装饰器
function logClass(params:any) {
    params.prototype.apiUrl = 'xxx'
    params.prototype.run = function () {
        console.log('i am run!')
    }
}

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

var http:any = new HttpClient()
console.log(http.apiUrl)
http.run()

装饰器工厂 (可传参)

function logClass(params:string) { // params 是传递的参数
    return function (target:any) { // target 是类的原型对象
         target.prototype.apiUrl = params   
    }
}

@logClass('/api/demo')
class HttpClient {
    constructor() {}
    getData() {}
}

var http:any = new HttpClient()
console.log(http.apiUrl)

支持多个装饰器

// 如果有多个装饰器,会先执行后面的
@logClass1('aaa') // 后
@logClass2('bbb') // 先
class HttpClient {}

装饰器执行顺序

属性 >> 方法 >> 方法参数 >>

属性装饰器

function logProperty(params:string) {
    return function (target:any, attr:any) {
        // target 是类的原型对象, attr 属性的名称 (url)
        target[attr] = params
    }
}

@logClass('/api/demo')
class HttpClient {
    @logProperty('http://www.baidu.com')
    public url:any | undefined;
    constructor() {}
    getData() {
        console.log(this.url)
    }
}

var http:any = new HttpClient()
console.log(http.apiUrl)

构造函数重载

替换构造函数

function logClass (target:any) {
    return class extends target {
        apiUrl:any = '我是修改后的构造函数 apiUrl'
        getData () {
            console.log(this.apiUrl + ' - next')
        }
    }
}

@logClass
class HttpClient {
    public apiUrl:string | undefined;
    constructor() {
        this.apiUrl = '我是构造函数 apiUrl'
    }
    getData() {
        console.log(this.apiUrl)
    }
}

var http = new HttpClient()
http.getData()

方法装饰器

如何替换/修改当前的方法

示例:将传入参数 强制修改为 String 类型

// 方法装饰器
function get() {
    return function (target:any, methodName:any, desc:any) {
        console.log(target) // 类的原型对象
        console.log(methodName) // 方法名
        console.log(desc) // 方法的属性Object
        console.log(desc.value) // 方法值
        
        // 将传入参数 强制修改为 String 类型
        // -------------------------------------
        var orginMethod = desc.value
        desc.value = function (..args:any[]) {
            args = args.map(value => {
                return String(value)
            })
            // 修改(没有这句则是替换)
            orginMethod.apply(this, args)
        }
        // -------------------------------------
    }
}

class HttpClient {
    public url:string | undefined;
    constructor() {}
    @get()
    getData(..args:any[]) {
        console.log(args)
        // ['123', 'aaa']
    }
}

var http:any = new HttpClient()
http.getData(123, 'aaa')

参数装饰器

比较少用

function logParams (params:any) {
    return function (target:any, methodName:any, paramIndex) {
        console.log(params) // abc
        target.apiUrl = params
    }
}

class HttpClient {
    ..
    getData(@logParams('abcd') uuid:any) {
        console.log('uuid:' + uuid)
    }
}

var http:any = new HttpClient()
http.getData(123456)
console.log(http.apiUrl)
// uuid:123456
// abcd

欢迎技术指正与交流,转载请注明出处
https://www.imure.cn/2019/10/25/Typescript-Decorator/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值