• 【TypeScript】何为装饰器


    1.什么是装饰器

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

    通俗的来说就是一个方法,可以注入到类,方法,属性参数上来扩展类,属性,方法,参数的功能

    2.装饰器的分类

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

    3.装饰器的写法:

    • 普通装饰器(无法传参)
    • 装饰器工厂(可以传参)

    4.类装饰器

    在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数,可以用来监视,修改类定义。

    // 装饰器 (普通装饰器)
    function logClass(params: any) {
        console.log(params)  // params就是当前类
        params.prototype.apiUrl = 'http://www.58.com' // 动态拓展属性
        params.prototype.run = function() {} // 动态扩展方法
    }
    
    @logClass
    class HttpClient {
        constructor() {
            
        }
        
        getData() {
            
        }
    }
    
    var http: any = new HttpClient()
    console.log(http.apiUrl) // http://www.58.com
    
    
    // 装饰器(装饰器工厂)
    function logClass(params: string) {
        return function(target: any) { // target 就是当前类
            console.log(target)
            console.log(params)
        }
        target.prototype.apiUrl = params
    }
    
    @logClass2('http://www.58.com')
    class HttpClient {
        constructor() {
            
        }
        
        getData() {
            
        }
    }
    
    // 装饰器应用例子---重载类的属性方法
    function logClass3(target: any) {
        return class exntends target {
            apiUrl: any = '我是修改后的数据'
            getData() {
                console.log('----'+this.apiUrl)
            }
        }
    }
    
    @logClass3
    class HttpClient {
        public apiUrl: string | undefined
        constructor() {
            this.apiUrl = '初始值'
        }
        
        getData() {
            console.log(this.apiUrl)
        }
    }
    
    var http:any = new HttpClient()
    http.getData() // ----我是修改后的数据
    

    5.属性装饰器

    function logProperty(params: any) {
        return function(target: any, attr: any) {
            console.log(target) // 当前对象
            console.log(attr) // 属性名称 打印了url
            target.attr = params;
        }
    }
    
    class HttpClient {
        @logProperty('http://www.58.com')
        public url: any | undefined
        constructor() {
            
        }
        
        getData() {
            console.log(this.url)
        }
    }
    
    var http = new HttpClient()
    http.getData() // http://www.58.com
    

    6.方法装饰器

    它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义

    方法装饰会在运行时传入3个参数:

    • 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
    • 成员的名字
    • 成员的属性描述符
    function get(params: any) {
        return function(target: any, methodName: any, desc: any) {
            console.log(target) // 原型对象 HttpClient对象(这个例子中)
            console.log(methodName) // 方法名称 getData
            console.log(desc) // 方法里的描述信息
            
            target.apiUrl = 'xxx' // 修改值
            target.run = function() { // 拓展方法
                console.log('run')
            }
            
            // 修改装饰器的方法 把修饰器方法里面传入的所有参数改为string类型
            // 1. 保存当前的方法
            var oMethod = desc.value;
            desc.value = function(...args: any[]) {
                args = args.map((value) => {
                    return String(value)
                })
                console.log(args)
                
                // 修改方法
                oMthod.apply(this, args)
            }
        }
    }
    
    class HttpClient {
        public url: any | undefined
        constructor() {
            
        }
        @get('http://www.58.com')
        getData(...args: any[]) {
            console.log(this.url)
        }
    }
    
    var http = new HttpClient()
    console.log(http.apiUrl)
    http.run()
    
    

    7.方法参数装饰器

    参数装饰器表达式会在运行时当做函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数:

    • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
    • 参数的名字
    • 参数在函数参数列表中的索引
    function logParams(params: any) {
        return function(target: any, methodName: any, paramsIndex: any) {
            console.log(target) // 原型对象
            console.log(methodName) // getData
            console.log(paramsIndex) // 0
            console.log(params) // xxx
            
            target.url = params
        }
    }
    
    class HttpClient {
        public url: any | undefined
        constructor() {
            
        }
        
        getData(@logParams('xxx') uuid: any) {
            console.log(uuid) // 123456
        }
    }
    
    var http = new HttpClient()
    http.getData(123456) 
    

    8.装饰器执行顺序

    属性》方法》方法参数》类
    如果有多个同样的装饰器,会先执行后面的

    // 伪代码
    ...
    @logClass1('类装饰器1')
    @logClass2('类装饰器2')
    class HttpClient {
        @logAttribute('属性装饰器')
        public url: string
        
        @logMethod('方法装饰器')
        constructor() {}
        
        getData(@logParam1('参数装饰器1') attr1: any, @logParam2('参数装饰器2') attr2: any) {}
    }
    
    
    // 属性参数器
    // 方法装饰器
    // 参数装饰器2
    // 参数装饰器1
    // 类装饰器2
    // 类装饰器1
    
    
    
  • 相关阅读:
    Tempter of the Bone
    CODE[VS]1160 蛇形矩阵
    CODE[VS] 1205 单词翻转
    CODE[VS] 1204 寻找子串位置
    a little sweet~
    我多喜欢你,你会知道
    P1474 货币系统 Money Systems
    P1096 Hanoi双塔问题
    P1209 [USACO1.3]修理牛棚 Barn Repair
    下一秒
  • 原文地址:https://www.cnblogs.com/fe-linjin/p/11336548.html
Copyright © 2020-2023  润新知