本书未发布

装饰器

未匹配的标注

类装饰器

function addNameAndEat(target: Function) {
    // target 就是要装饰的类
    target.prototype.name = 'xiaoming'
    target.prototype.eat = function(){}
}

@addNameAndEat
class Person {
    name: string
    eat: Function
    constructor(){}
}

let p:Person = new Person()
console.log(p.name)
p.eat()

类装饰器工厂

  • 装饰器可以传递参数
function addNameAndEatFactory(name: string) {
    return function addNameAndEad(target: Function) {
        // target 就是要装饰的类
        target.prototype.name = name
        target.prototype.eat = function(){}
    }
}

@addNameAndEatFactory('xiaoming')
class Person {
    name: string
    eat: Function
    constructor(){}
}

let p:Person = new Person()
console.log(p.name)
p.eat()

属性装饰器

  • 可以装饰属性, 也可以装饰方法

    namespace a {
      //如果装饰的是实例属性的话, 那么 target 是构造函数的原型
      function upperCase(target: any, propertyKey: string) {
          let value = target[propertyKey]
          const getter = () => value
          const setter = (newVal: string) => {value = newVal.toUpperCase()}
    
          if (delete target[propertyKey]) {
          Object.defineProperty(target, propertyKey, {
              get: getter,
              set: setter,
              enumerable: true,
              configurable: true
          })
          }
      }
    
      // 如果装饰的是静态属性的话, 那么 target 是构造函数本身
      function staticPropertyDecorator(target: any, propertyKey: string) {
          console.log(target, propertyKey)
      }
    
      function noEnumerable(target: any, propertyKey: string, descriptor: PropertyDecorator) {
          // 变成不可枚举
          descriptor.enumerable = false
      }
    
      // 方法装饰器
      function toNumber(target: any, propertyKey: string, descriptor: PropertyDecorator) {
          let oldMethod = descriptor.value
          descriptor.value = function(...args: any[]) {
              args = args.map(item => parseFolat(item))
              return oldMethod.apply(this, args)
          }
      }
    
      class Person {
          // 装饰 name
          @upperCase
          name:string = 'xiaoming'
    
          @staticPropertyDecorator
          public static age: number = 18
          constructor() {}
    
          @noEnumerable
          getName() {
              console.log(this.name)
          }
    
          @toNumber
          sum(...args: any[]) {
              return args.reduce((accu: number, item: number) => accu+ item,0)
          }
      }
    }

参数装饰器

namespace b {
    // 如果修饰的是静态成员, 那么 target 就是构造函数, 如果是非静态成员, target 就是构造函数原型
    // methodName 是方法名称
    // paramIndex 是参数的索引
    function addAge(target: any, methodName, paramIndex: number) {
        target.age = 10
    }

    class Person {
        age: number

        login(username: string, @addAge password: string) {
            console.log(this.age, username, password)
        }
    }
}

装饰器的执行顺序

  • 一般是从内往外执行, 先内后外
  • 类装饰器是最后执行的, 如果一个类有多个装饰器, 那么后写的装饰器先执行
  • 方法和方法参数中的装饰器, 会先执行参数的装饰器, 然后再执行方法的
  • 方法和属性的装饰器, 谁在前面, 就先执行谁

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 查看所有版本


暂无话题~