当前位置: 首页>前端>正文

typescript map指定类型 typescript metadata

首先我们来说一下什么是装饰器,其实TS中的装饰器和很多的静态语言(Java,C#)等中的装饰器其实是一样的,它会为被装饰的内容添加一些特定的内容,而装饰器本身就是一个方法,它需要遵循两个条件: 1. 不能够修改被装饰内容的源代码 2. 不能够修改被装饰内容的调用

那么,我们进来就来说说在Ts中如何使用装饰器:
(注:在TS中使用装饰器之前我们需要现在tsconfig.json这个配置文件中配置"experimentalDecorators" 和 "emitDecoratorMetadata"这两个选项为true)

  1. 在类中使用装饰器:
    首先我们定义一个Person类:
class Person {
    constructor(public name: string) {}
}

此时我们使用装饰器为这个类添加一个age的属性:

// 这里我们使用了泛型定义了这个函数的参数类型: <T extends new (...args: any[]) => {}>
// 这个泛型T继承的内容,我们可以将它看做是一个类的类型,我们定义的类装饰器函数接收到的是一个类的构造函数
function addAgeDecorator<T extends new (...args: any[]) => {}>(constructor: T) {
	// 装饰器函数返回一个新的类,并且这个类继承自它所装饰的那个类, 在这个返回的类中我们加上了一个age属性
     return class extends constructor {
         age = 18;
     }
}

这时我们即可以这样去使用:

@addAgeDecorator
class Person {
    constructor(public name: string) {}
}

这里再做一些说明:

  1. 装饰器在调用时使用@符号
  2. 装饰器的执行时机是在类的定义完成后立即被执行,完成对类的装饰
  3. 装饰器的这个函数中拿到的是类的构造函数,能够完成对类的一些修改
  4. 一个类可以被多个装饰器所装饰,当存在多个装饰器时,装饰器的执行顺序是从下到上的
  5. 如果我们想要在装饰器中进行一定的逻辑处理的话,推荐使用工厂模式对装饰器函数进行封装,例如我们可以这样书写上面的那个装饰器:
function addAgeDecorator() {
    return function <T extends new (...args: any[]) => {}>(constructor: T) {
        return class extends constructor {
            age = 20;
        }
    }
}
  1. 在方法中使用装饰器:
    有如下一个类:
class Person {
    constructor(public _name: string) {}
    get name(){
		return this._name
	}
}

我们使用一个函数装饰器来装饰这个getter

// 在方法装饰器中我们可以接收到两个参数:
// target: target表示的是当前方法所在类的一个显式原型:prototype
// key: key参数表示的是当前所装饰方法的名字
function getNameDecorator(target: any, key: string) {
     console.log(target, key);
}

此时即可以使用@getNameDecorator去装饰getter方法了
关于方法装饰器的几点补充:

  1. 方法装饰器可以接收到所装饰方法所在类的prototype和方法名字两个参数
  2. 当所装饰的是一个类的静态方法时,还可以接收到第三个参数: descriptor: PropertyDescriptor;这是一个控制器,可以直接对所装饰的方法进行控制
  3. 不能同时对getter和setter使用相同的装饰器
  1. 属性的装饰器:
    (由于属性装饰器的使用和上面相似,所以这里就不在定义相应的类了)
function nameDecorator(target: any, key: string): any {
       const descriptor: PropertyDescriptor = {
           writable: false
       }
       return descriptor;
  }

以上我们便定义了一个属性装饰器,它的定义和方法装饰器相似,但是有几点区别:

  1. 属性装饰器接收到的参数仍然有两个: target仍然是当前对象的prototype, key是所装饰的属性的名称
  2. 在属性装饰器中不存在descriptor,但是我们可以在属性装饰器中创建一个descriptor去替换原有属性的descriptor,如上面的例子,我们即在属性装饰器中创建了一个descriptor
  3. 我们在属性装饰器中使用target[key]的形式修改属性的值修改的是类prototype上的值,并不是修改的属性的真实的值,而我们直接去修改属性实例上的值是无法完成的,大家可以根据装饰器的调用时机进行理解
  1. 参数装饰器:
function paramDecorator(target: any, method: string, paramIndex: number): any {
    console.log(target, method, paramIndex)
}

如上所示,参数装饰器的定义和前两种装饰器的定义也是相似的,参数装饰器装饰的是我们传递的方法的参数,使用时也是直接使用@符号即可
参数装饰器中的参数:

  • 参数装饰器的第一个参数仍然是当前类的原型
  • 参数装饰器的第二个参数是参数所在的方法名
  • 参数装饰器的第三个参数是参数所在方法中的位置,及为第一个参数是则为0,以此类推


https://www.xamrdz.com/web/27w1931429.html

相关文章: