TS装饰器3分钟上手

装饰器

前言

angularjs运用装饰器会比较多,它也是ts的一大特性,下面知识能够让大家对ts装饰器有一个初步的了解.

基础知识

装饰器:本质是一个方法,可以注入到类、方法、属性参数上来拓展类、属性、方法、参数的功能.
分类:类装饰器、属性装饰器、方法装饰器、方法参数装饰器.
装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参).
各种装饰器执行顺序:属性装饰器 > 方法参数装饰器 > 方法装饰器 > 类装饰器;如果每种有多个,则从后往前执行

类装饰器

在不修改当前类的前提下,动态给类添加属性和方法

// 普通装饰器(无法传参)
function Log(target: any) {
  // console.log(target)
  // target 代表当前类

  target.prototype.apiUrl = 'http://www.api.com'

  target.prototype.send = function() {
    console.log(`send invoke`)
  }
}

// 装饰器工厂(可传参)
function LogFactory(params: any) {
  return function(target: any) {
    // console.log(target)
    // console.log('------')
    // console.log(params)
    target.prototype.apiUrl = params.apiUrl
  }
}

// 普通装饰器(重写构造器方法或是其它方法)
function LogOverride(target: any) {
  return class extends target {
    apiUrl = 'http://baidu.com'

    getData() {
      console.log('重写后的apiUrl:', this.apiUrl)
    }
  }
}

//@Log //普通装饰器(无法传参)
// @LogFactory({apiUrl: 'http://baidu.com'})
@LogOverride
class HttpClient1 {
  public apiUrl: string | undefined

  constructor() {
    this.apiUrl = 'http://baidu.com'
  }

  getData() {
    console.log(this.apiUrl)
  }
}

const httpClient1: any = new HttpClient1()
httpClient1.getData()
// console.log(httpClient1)
// console.log(httpClient1.apiUrl)
// httpClient1.send()

属性装饰器:

接收两个参数:

  • 参数1 类的构造函数(静态成员)/原型对象(实例成员)
  • 参数2 成员的名字
function Property(params: string) {
  // 参数1 类的构造函数(静态成员)/原型对象(实例成员)  prototype === HttpClient2.prototype
  // 参数2 成员的名字
  return function(prototype: any, name: string) {
    prototype[name] = params
  }
}
class HttpClient2 {
  @Property('http://baidu.com')
  public apiUrl: string | undefined

  getData() {
    console.log('apiUrl is ', this.apiUrl)
  }
}

const httpClient2 = new HttpClient2()
httpClient2.getData()

方法装饰器

接收三个参数:

  • 参数1 类的构造函数(静态成员)/原型对象(实例成员)
  • 参数2 方法的名字
  • 参数3 方法描述
// 方法装饰器
function Method(params: string) {
  // 参数1 类的构造函数(静态成员)/原型对象(实例成员)  prototype === HttpClient3.prototype
  // 参数2 方法的名字
  // 参数3 方法描述
  return function(prototype: any, name: string, desc: any) {
    // desc.value === getData
    // console.log(desc)

    // 保存之前的方法
    const oldMethod = desc.value

    desc.value = function(...args: any) {
      args = args.map((item: any) => {
        return String(item)
      })

      console.log('方法装饰器内部 ', args)

      // console.log('method invoke start -----', new Date() - 0)
      oldMethod.apply(this, args)
      // console.log('method invoke end -----', new Date() - 0)
    }
  }
}

// 方法参数装饰器
function MethodParams(params: any) {
  /**
   * 参数1 类的构造函数(静态成员)/原型对象(实例成员)
   * 参数2 方法的名字
   * 参数3 参数的索引
   */
  return function(prototype: any, name: string, index: number) {
    console.log('---------------------------------------')
    console.log(params)
    console.log(prototype)
    console.log(name)
    console.log(index)
  }
}

class HttpClient3 {
  @Method('xxx')
  getData(...args: any[]) {
    console.log('getData method invoke', args)
  }

  setData(
    @MethodParams('name') name: string,
    @MethodParams('age') age: number
  ) {
    console.log(`this person name is ${name} age is ${age}`)
  }
}

const httpClient3 = new HttpClient3()
httpClient3.getData(123, 'nihao', true)
httpClient3.setData('zhangsan', 31)

猜你喜欢

转载自blog.csdn.net/qq_44855897/article/details/107919332