typescript 装饰器 Decorators

67 阅读2分钟

案例

@frozen class Foo {
    
    @configurable(false) // 可配置的
    @enumberable(true) // 可枚举的
    method () {}
    
    
    @throttle(500) // 节流
    expensiveMethod () {}
}

上面代码一共使用了四个装饰器

  • 一个用在类本身(@frozen)
  • 另外三个用在类方法(@configurable()、@enumberable()、@throttle())

不仅增加了代码的可读性,清晰地表达了意图

而且提供一种方便的手段,增加或修改类的功能

装饰器API类型

type Decorator = (
    
    value: Input,
    
    context: {
    
        // 装饰类型: 字符串 (可能的取值有: class、method、getter、setter、field、accessor)
        kind: string;
        
        // 被装饰的值的名称
        name: string | symbol;
        
        //  对象: 存值器和取值器
        access: {
            get?(): unknown;
            set?(value: unknown): void
        };
        
        // 私有元素: 布尔值
        private?: boolean;
        
        // 静态元素: 布尔值
        static?: boolean;
        
        // 函数,允许用户增加初始值逻辑
        addInitializer?(initializer: () => void): void
    }
    
) => Output | void

装饰器函数,两参数。

  • value: 被装饰的值,某些情况下可能是undefined(装饰属性时)
  • context: 上下文信息对象

装饰器函数的返回值,是一个新版本的装饰对象,但也可以不返回任何值(void)


1、装饰器和继承的区别

2、配置typescript装饰器环境

3、typescript类装饰decorator器使用基础

const moveDecorator = (target) => {
    
}

@moveDecorator
class Tank {}

@moveDecorator
class Player {}

class Tank {} 是装饰器 moveDecorator 的 参数,也就是target是class Tank这个类

class Player {} 也是如此

获取位置

const moveDecorator = (target: Function) => {
    target.prototype.getPosition = (): { x: number, y: number } => {
        return { x: 100, y: 200 }
    }
}

@moveDecorator
class Tank {
    public getPosition() {} // 这个是为了下面typescript中t找不到getPosition的报错加的, 也可以去掉加断言
}

const t = new Tank()
console.log(t.getPosition()) // { x: 100, y: 200 }

也可以去掉,加断言

const moveDecorator = (target: Function) => {
    target.prototype.getPosition = (): { x: number, y: number } => {
        return { x: 100, y: 200 }
    }
}

@moveDecorator
class Tank {
}

const t = new Tank()
console.log((t as any).getPosition()) // { x: 100, y: 200 }
// 也可以 console.log((<any>t).getPosition()) // { x: 100, y: 200 }

语法糖

@decoratorName 这种就是语法糖的形式。装饰器归根结底还是跟原型链脱不了干系。

所以如果是类的装饰器,就是把类的构造函数传到函数里面作为参数,只不过我们使用这种@decoratorName语法糖这种形式会自动帮我们操作,不需要我们人为的调用。

执行步骤

装饰器的执行步骤如下。

  1. 计算各个装饰器的值,按照从左到右,从上到下的顺序。
  2. 调用方法装饰器。
  3. 调用类装饰器。

特点

使用装饰器来包装代码,语法更加简单优雅,编写的代码可读性更高也更易于理解。

装饰器其实本质上来讲就是一个函数。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天 点击查看活动详情