1.装饰器的概念
装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以修改类的行为。 通俗的讲装饰器就是一个函数/方法,可以注入到类、方法、属性、参数上来扩展类、属性、方法、参数的功能。 在Java中,常常被叫作注解。
装饰器本质就是一个函数,但它是一个返回函数的函数,它所带来的好处就是不需要关心原有函数的逻辑,加上装饰器就自动帮你做点特定的事情。
2.手写装饰器
2.1 属性装饰器
我们在组件里定义一个变量 result,并用一个表情装饰器去修饰。
@Emoji() public result = 'When will the epidemic end in Shanghai?';
在html模板中去使用
<p>{{ result }}</p>
接下来就是手写这个表情装饰器了,可以新建一个文件夹 decorators,并在该文件夹下创建文件 index.ts
export function Emoji() {
// target 是装饰器的目标对象,此处即为组件; key 是应用装饰器的变量,此处为 result
return (target: object, key: string) => {
let val = target[key];
const getter = () => {
return val;
}
const setter = (value: string) => {
val = `😂 ${value} 😂`
}
// 附加到原来对象上
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
})
}
}
为什么要这样一个类型,如果它是一个返回函数的函数,Emoji 想作用于 result 这个属性的话,首先要知道位于哪个类当中,然后再去找该属性。所以参数 target 对应的就是这个类,然后去找它的 result 属性,任何一个类在某种角度上来讲和字典/索引对象很像,这些属性都可以看作其里面的索引值。Emojs 函数写好后,再在组件中将写好的装饰器导入进来。
2.2 方法装饰器
在html模板中写一个click事件
<p (click)="handleClick()">Hello TypeScript!</p>
在组件中写一个确认对话框的装饰器:
@Confirmable('确认要执行吗?')
public handleClick(): void {
console.log('点击已执行');
}
同样在文件夹 decorators下的文件index.ts中手写装饰器
export function Confirmable(message: string) {
return (
target: object,
key: string,
descriptor: PropertyDecorator
) => {
// 先把装饰器修饰的函数赋给一个变量
const original = descriptor.value;
// 然后替换成下面的函数
descriptor.value = function(...args: any[]) {
// 执行弹出对话框
const allow = window.confirm(message);
// 如果确认则执行原有函数逻辑
if (allow) {
const result = original.apply(this, args);
return result;
}
return null;
}
return descriptor;
}
}
descriptor 就是对一个属性的描述
PropertyDecorator 这个类型也是 JavaScript 中的一个概念,在一个组件类当中,对于每一个属性都有一个描述符,里面有该属性的值、set、get等。因为装饰器修饰的是函数 handleClick,所以在 index.ts 中先将原来的函数放到一个变量里,然后对其进行处理。为什么要进行处理?
因为要弹出一个对话框,根据对话框选择的情况决定是否执行原来的函数。首先将属性描述符 descriptor 里的 value 替换掉(这个 value 其实就是一个函数),换上一个匿名函数,在其中执行弹出对话框的操作,弹出要有信息,正好装饰器里有接收一个参数 message,对应的就是装饰器里写的字符串。根据返回结果(布尔值)决定是否执行原有的函数。
为什么最后要返回 descriptor?
应用到方法的装饰器就是这样规定的,具体可以看一下 typescript 文档 www.typescriptlang.org/docs/handbo…
一般情况下,使用框架提供的装饰器就可以了。那么什么场景需要使用装饰器?由于装饰器就是一个函数,所以我们使用装饰器往往是需要复用某些代码逻辑,但是如果单纯是复用代码,普通函数也可以,那么装饰器的优势其实是它提供了一种类似配置的方式实现复用,这样会降低门槛,让团队协作起来更容易,也更规范。但是请注意,装饰器不要滥用,装饰器满天飞之后就失去了意义。