如果没有用过装修器,很多人应该跟我一样对装修器详细是个什么东西没什么概念,只知道它是一个样子像 @decorator
的东西,会对被装修的东西产生影响,可是详细是怎么影响的不清楚。那么,就先用尽量简洁的言语来解说什么是装修器:
装修器本质上便是一个包装函数。它能够拿到被装修的内容,对其进行自界说加工和处理。
一个抽象的解说之后,来看一个简略的比如:
// 装修器完成
function decorateClass<T>(constructor: T) {
console.log('decorateClass');
}
// 作为类装修器
@decorateClass
class A {
constructor() {}
}
// 输出成果: decorateClass
装修器能够拿到类 A,对其进行加工。
装修器的完成
刚刚已经看了一个简略的装修器比如,可是装修器的完成其实不止这种方式,简略总结便是:
-
不支持参数的装修器
function decorator(target) { // do something with 'target' ... }
-
支持参数的装修器(装修器工厂) 其实是一个工厂函数,回来一个装修器办法。
function decorator(value: string) { // this is the decorator factory, it sets up // the returned decorator function return function (target) { // this is the decorator // do something with 'target' and 'value'... }; }
装修器能够使用在哪些目标上?
知道装修器的基本概念之后,自然也需要知道到底能够用来装修什么东西,简略总结便是类相关的它都能够装修:
- 类(Class Decorators)
- 类特点(Property Decorators)
- 类拜访器(Accessor Decorators)
- 类办法(Method Decorators)
- 类办法参数(Parameter Decorators)
类装修器 – Class Decorators
效果:能够拿到类的结构函数,能够修正或替换类的界说
效果目标:类
参数:类的结构函数
回来值:如果带回来值,则需要是一个结构函数,该结构函数将替换原本类的完成
如下示例,回来一个新的类替换原本类的完成:
function decorateClass(constructor) {
return class B extends constructor {
name = 'B';
age = 18;
}
}
@decorateClass
class A {
name = 'A';
constructor() {
}
}
const a = new A();
console.log(a.name, a.age) // 输出 B 18
function decorateClass(name) {
return function (constructor) {
return class B extends constructor {
name = name || 'B';
age = 18;
};
};
}
@decorateClass('name')
class A {
name = 'A';
constructor() {}
}
const a = new A();
console.log(a.name, a.age); // 输出 name 18
类特点装修器 – Property Decorators
效果:能够拿到特点名,对特点完成署理等操作
效果目标:静态成员、实例成员
参数:
- target:关于静态成员则是结构函数,关于实例成员则是类的原型
- key:成员名
回来值:无
如下示例,对装修的特点完成署理,检查设置的值是否合法:
function validProperty(validNameList: string[]) {
return function (target: any, propertyKey: string) {
let value: string = target[propertyKey];
const get = function () {
console.log(`${propertyKey} value: ${value}`);
return value;
};
const set = function (val: string) {
console.log('validNameList', validNameList);
if (!validNameList.includes(val)) {
console.warn(`invalid name: ${val}`);
return;
}
value = val;
};
Object.defineProperty(target, propertyKey, { set, get });
};
}
class People {
@validProperty(['a', 'b'])
name: string;
constructor(name: string) {
this.name = name;
}
}
const people = new People('a');
console.log(people.name); // a
people.name = 'cccc'; // invalid name: cccc
console.log(people.name); // a
类拜访器装修器 – Accessor Decorators
效果:能够修正或替换拜访器的界说
效果目标:静态拜访器、实例拜访器
参数:
- target:关于静态拜访器则是结构函数,关于实例拜访器则是类的原型
- key:拜访器名
- descriptor:特点描述符,即
Object.getOwnPropertyDescriptor(target,key)
回来值:如果带回来值,则需要是一个特点描述符,并作为拜访器的特点描述符
如下示例,修正拜访器的特点描述符:
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class People {
@validProperty(['a', 'b'])
firstName: string;
lastName: string;
@enumerable(false)
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
}
类办法装修器 – Method Decorators
效果:能够修正或替换办法的界说
效果目标:静态办法、实例办法
参数:
- target:关于静态办法则是结构函数,关于实例办法则是类的原型
- key:办法名
- descriptor:特点描述符,即
Object.getOwnPropertyDescriptor(target,key)
回来值:如果带回来值,则需要是一个特点描述符,并作为拜访器的特点描述符
如下示例,增强办法,弥补办法弃用提示:
const deprecated = (deprecationReason: string) => {
return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
const wrapperFn = (...args: any[]) => {
console.warn(`Method ${memberName} is deprecated with reason: ${deprecationReason}`);
propertyDescriptor.value.apply(target, args)
}
return {
value: wrapperFn,
}
}
}
class TestClass {
static staticMember = true;
instanceMember: string = "hello"
@deprecated("Use another static method")
static deprecatedMethodStatic() {
console.log('inside deprecated static method - staticMember =', this.staticMember);
}
@deprecated("Use another instance method")
deprecatedMethod () {
console.log('inside deprecated instance method - instanceMember =', this.instanceMember);
}
}
TestClass.deprecatedMethodStatic();
const instance = new TestClass();
instance.deprecatedMethod();
类办法参数装修器 – Parameter Decorators
效果:待弥补
效果目标:静态办法、实例办法
参数:
- target:关于静态成员则是结构函数,关于实例成员则是类的原型
- key:参数名
- index:参数在函数参数列表中的索引
回来值:无
如下示例:
function print(target: Object, propertyKey: string, parameterIndex: number) {
console.log(`Decorating param ${parameterIndex} from ${propertyKey}`);
}
class TestClass {
testMethod(param0: any, @print param1: any) {}
}
小结
装修器的使用
待弥补
参考
- Decorators
- Typescript 装修器及使用场景浅析