美文网首页
TS 装饰器(1): 基础用法

TS 装饰器(1): 基础用法

作者: 菜鸡前端 | 来源:发表于2022-02-26 22:56 被阅读0次

    TS 装饰器(1): 基础用法

    1、什么是装饰器

    装饰器是通过添加标注的方式,来对类型进行扩展的一种方式。

    • 只能在类中使用
    • 减少冗余代码量
    • 提高代码扩展性

    2、装饰器语法

    装饰器的使用非常简单,装饰器本质就是一个函数,在特定的位置调用装饰器函数即可对数据(类、方法、甚至参数等)进行扩展。下面例子演示给 MyTestableClass 类添加静态属性 isTestable:

    @testable
    class MyTestableClass {}
    
    function testable(target) {
      target.isTestable = true;
    }
    
    MyTestableClass.isTestable // true
    

    3、装饰器的分类

    装饰器 是一个函数,它可以通过 @funName 在类、方法、访问符、属性、参数上,对它们进行包装,然后返回一个包装后的目标对象(类、方法 、访问符、属性、参数)。

    3.1、类装饰器

    类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。下面例子演示给 MyTestableClass 类添加静态属性 isTestable:

    源代码:

    @testable
    class MyTestableClass {}
    
    function testable(target) {
      target.isTestable = true;
    }
    
    MyTestableClass.isTestable // true
    
    image

    3.2、类方法装饰器

    方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

    • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
    • 成员的名字。
    • 成员的属性描述符。

    下面的例子演示让类的方法变为只读。

    (1) 实例方法

    function readonly(target, name, descriptor) {
        descriptor.writable = false;
        return descriptor;
    }
    class Cat {
        @readonly
        say() {
            console.log("meow ~");
        }
    }
    
    image

    (2) 静态方法

    class MyTestableClass {
        @testable
        static sleep() {}
    }
    
    function testable(target, name, descriptor) {
      target.isTestable = true;
    }
    
    MyTestableClass.isTestable // true
    

    3.3、类属性装饰器

    属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:

    • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
    • 成员的名字。

    属性描述符不会做为参数传入属性装饰器,这与TypeScript是如何初始化属性装饰器的有关。官方文档有说明。

    class MyTestableClass {
        @testable
        name: string;
        constructor(name: string) {
            this.name = name;
        }
    }
    
    function testable(target, name) {
      console.log(arguments)
    }
    
    image

    3.4、参数装饰器

    参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

    • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
    • 成员的名字。
    • 参数在函数参数列表中的索引。

    注意  参数装饰器只能用来监视一个方法的参数是否被传入。参数装饰器的返回值会被忽略。

    class Greeter {
        greeting: string;
    
        constructor(message: string) {
            this.greeting = message;
        }
    
        greet(@required name: string) {
            return "Hello " + name + ", " + this.greeting;
        }
    }
    
    image

    4、装饰器的执行顺序

    1. 实例装饰器:属性装饰 -> 访问器装饰 -> 参数装饰 => 方法装饰
    2. 静态装饰器: 属性 => 访问器 => 参数 => 方法
    3. 类装饰器

    5、复合装饰器

    @d1
    @d2
    class Greeter {
      greeting: string;
      constructor(message: string) {
        this.greeting = message;
      }
    
      greet() {
        return "Hello, " + this.greeting;
      }
    }
    
    function d1(target: Function) {}
    function d2(target: Function) {}
    

    6、装饰器工厂

    如果我们需要给装饰器执行过程中传入一些参数的时候,就可以使用装饰器工厂来实现,它返回一个装饰器函数。

    @Controller('user')
    class Greeter {
      greeting: string;
      constructor(message: string) {
        this.greeting = message;
      }
    
      greet() {
        return "Hello, " + this.greeting;
      }
    }
    
    function Controller(path: string) {
      return function (target: Function) {
        (target as any).path = path;
      }
    }
    

    相关文章

      网友评论

          本文标题:TS 装饰器(1): 基础用法

          本文链接:https://www.haomeiwen.com/subject/uoucrrtx.html