前言
继上篇文章后,继续对装饰器进行学习,本文作为学习记录以及学习分享。下面代码中所有的any类型只是不想让demo在ts中出现报错。在实际开发中都可根据实际情况来进行替换。
什么是成员装饰器?
指的是类的成员的装饰器。类成员一共分为两类:属性和方法。下面来分享一下成员装饰器的具体用法。
属性装饰器
属性装饰器是一个函数,该函数接受两个参数。
第一个参数需要根据具体情况来决定。
- 如果是实例属性,第一个参数为
类的原型(prototype)。 - 如果是静态属性,第一个参数为
类本身。
第二个参数固定为一个字符串,表示属性名。
既然知道了属性装饰器的本质,那就尝试书写一下:
实例属性装饰器
type decoratorType = new (...args: any) => object;
function funcDecorator(target: any, key: string) {
console.log(target === A.prototype, key);
if (!target.__props) {
target.__props = [];
}
target.__props.push(key);
}
class A {
@funcDecorator
prop1: string;
@funcDecorator
prop2: string;
}
console.log((A.prototype as any).__props);
以上代码为两个类的实例属性添加了装饰器。所以自然而然属性装饰器会运行两次。让我们来看一下运行结果吧~
因为被装饰的是实例属性,所以装饰器的第一个参数为类的原型。这从运行结果中可以验证到。那既然能获取到原型,就可以根据实际情况书写多种逻辑了。
静态属性装饰器
function funcDecorator(target: any, key: string) {
console.log(target, key);
}
class A {
@funcDecorator
static prop2: string;
}
当修饰类的静态属性时,装饰器第一个参数获取到的是类本身。以下为运行结果:
当然,属性装饰器也可以使用装饰器工厂的形式来书写,用来接受参数参与逻辑。
function funcDecorator(prop: any) {
return function (target: any, key: string) {
console.log(target, key);
};
}
class A {
@funcDecorator("我是属性装饰器")
static prop2: string;
}
方法装饰器
方法装饰器当然也是一个函数,该函数接受三个参数。
第一个参数也是需要根据具体情况来决定。
- 如果是实例方法,第一个参数为
类的原型(prototype)。 - 如果是静态方法,第一个参数为
类本身。
第二个参数固定为一个字符串,表示方法名。
第三个参数为属性描述对象。如果忘记了的话可以看一下这里。
function funcDecorator(prop: any) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
console.log(target, key, descriptor);
};
}
class A {
@funcDecorator("我是属性装饰器")
method1() {}
}
运行后输出结果为:
对于方法装饰器来说,可以通过属性描述对象来对这个方法做一些操作,比如是否可被遍历,设置getter/setter等等。
比如我想书写两个方法装饰器eumerable和useless。分别表示该方法可被遍历和提示该方法已经被启用。那就可以这么写:
function enumerable(target: any, key: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = true;
}
function useless(target: any, key: string, descriptor: PropertyDescriptor) {
descriptor.value = function () {
console.warn(`${key}方法已过期!`);
};
}
class A {
@enumerable
method1() {}
@useless
@enumerable
method2() {}
}
const a = new A();
for (const i in a) {
console.log(i);
}
a.method2();
个人认为装饰器对于通用逻辑和定制化逻辑都非常适用。
结尾
今天的学习和分享就到这了,如果不足欢迎指出!祝大家工作顺利,永无bug~