什么是装饰器
https://github.com/tc39/proposal-decorators
装饰器是ES2016提出来的一个提案,当前处于Stage 2阶段,关于装饰器的体验,可以点击 https://github.com/tc39/proposal-decorators查看详情。装饰器是一种与类相关的语法糖,用来包装或者修改类或者类的方法的行为,其实装饰器就是设计模式中装饰者模式的一种实现方式。
第一次看到装饰器的时候,立马就跟spring的注解关联起来了。两者都是可以在某一项任务前后嵌入额外的代码,就是AOP编程思想了。
装饰器有什么作用
在平时开发过程中,我们会发现代码中会有很多重复用到的代码片段,大部分时候我们通过提取封装成一个方法来使用。
不过封装方法后,需要改造代码的一小部分逻辑才能使用。
这时候装饰器的作用就来了,可以在不改变代码结构的同时,作为一个aop切面,注入代码,统一处理。
使用方式
-
在根目录创建一个jsconfig.json,如果是ts就是tsconfig.json网上查下配置,差不多
jsconfig.json
{ "compilerOptions": { "experimentalDecorators": true } }
-
编写装饰器,这里以比较常见的loading举例
export const loading = function(loadingKey, errorFn = function() {}) { return function(target, name, descriptor) { const fn = descriptor.value; // 这个是原来的方法,这里做一次保存 // 扩展原来的方法 descriptor.value = async function(...rest) { // 这里要使用function才能保证this的指向正确 try { this[loadingKey] = true; // 将loading设置为true return await fn.call(this, ...rest); // 执行原来的方法 } catch (error) { // 在调用失败,且用户自定义失败的回调函数时,则执行 this.utils.errorHanlde(error); errorFn && errorFn.call(this, error, ...rest); } finally { this[loadingKey] = false; // 最后无论如何 取消loading } }; }; };
装饰器的编写规则
- 装饰器是一个方法,允许传参(自定义)
- 方法最后要返回一个函数,函数的入参是target name descriptor
- target 装饰器所在的上下文
- name 装饰的方法名
- descriptor描述对象,descriptor.value() 为装饰的方法
-
使用
import { loading } from 'xxxx'; export default { methods: { // loading方法需要导入 @loading("loading") async handleConfirm() { await confirmReq(); } } }
这样就会在调用handleConfirm方法的时候,自动将this.loading设置为true,执行结束将this.loading设置为false
至此,我们就可以展开我们的想象力了,看看代码里面有什么可以统一抽取的代码
比如:
- confirm弹框
- 权限校验
- 出入参日志打印
- 方法执行时长日志打印
- …