自我学习js装饰器的使用

从接触到java后发现了一个非常好用的东西(注解)@Request @Override

使用注解可以简化代码,提高代码的可读性和可维护性。

经过百度发现前端也有类似的工具方法(装饰器),自己上手去学习下这个工具从0开始。

1.首先什么是装饰器

前端装饰器是一种用于增强HTML、CSS和JavaScript代码可维护性和可读性的工具。它通过在代码中添加注释和说明,使代码更加清晰易懂。

装饰器可以帮助开发者在代码中记录设计意图、代码规范和注意事项等信息,从而使代码更易于维护和重构。

2.为什么要使用装饰器

增加代码可读性和可维护性。

可以在运行时动态地修改和增强类、方法、访问符、属性或参数的行为。

可以实现AOP(面向切面编程)的编程功能。

3.装饰器如何优化代码

使用装饰器可以将一些通用的代码封装到装饰器中,然后在需要时将其应用到多个类或方法上,从而避免代码冗余。

装饰器可以用于实现类似于Java中的代理和装饰器的模式,例如在方法执行前后添加额外的逻辑,并将其包装到一个新的对象中。

4.简单写个装饰器的demo

我们在写后台时候最常用到的就是表单验证了,他的代码都是相同的,区别就是绑定的ref不一样,那我们可不可以通过装饰器给他拆出来呢,我们尝试去写一下。

最终代码实现就是

js 复制代码
/**
 * 表单验证装饰器
 * @param {*} refName - ref名称
 */
export function validate(refName) {
  return function (target, name, descriptor) {
    const fn = target[name]
    descriptor.value = function (...args) {
      this.$refs[refName].validate((valid) => {
        if (valid) {
          fn.call(this, ...args);
        } else {
          return false;
        }
      });
    };
  };
}

@validate()
submit(){
    console.log('request')
}

5.结合业务我们实现一个类似于el-form的rules验证

js 复制代码
export function validateParams(rules, config = { isMsg: true, type: 'warning' }) {
    const { isMsg = true, type = 'warning' } = config;
    return function (target, propertyKey, descriptor) {
      const originalMethod = descriptor.value;
      descriptor.value = function (...args) {
        const argNames = originalMethod.toString().match(/\(([^)]+)\)/)[1].split(',').map(name => name.trim());
        for (let i = 0; i < argNames.length; i++) {
          const argName = argNames[i];
          const arg = args[i];
          for (let ruleKey in rules) {
            const rule = rules[ruleKey];
            if (rule.objName === argName) {
              let value = arg[ruleKey];
              if (rule.isRequired && (value === null || value === undefined || value === '')) {
                if (isMsg) {
                  Message[type](rule.message ?? `参数 "${ruleKey}" 是必需的`);
                } else {
                  throw new Error(`参数 "${ruleKey}" 是必需的`);
                }
                return;  // 验证失败,不执行后续的验证和原始方法
              } else if (rule.test && !rule.test(value, this)) {  // 将Vue实例作为第二个参数传递给test函数
                if (isMsg) {
                  Message[type](rule.message);
                } else {
                  throw new Error(`参数 "${ruleKey}" 无效:${rule.message}`);
                }
                return;  // 验证失败,不执行后续的验证和原始方法
              }
            } else if (!rule.objName && ruleKey === argName) {
              if (rule.isRequired && (arg === null || arg === undefined || arg === '')) {
                if (isMsg) {
                  Message[type](rule.message ?? `参数 "${ruleKey}" 是必需的`);
                } else {
                  throw new Error(`参数 "${ruleKey}" 是必需的`);
                }
                return;  // 验证失败,不执行后续的验证和原始方法
              } else if (rule.test && !rule.test(arg, this)) {  // 将Vue实例作为第二个参数传递给test函数
                if (isMsg) {
                  Message[type](rule.message);
                } else {
                  throw new Error(`参数 "${ruleKey}" 无效:${rule.message}`);
                }
                return;  // 验证失败,不执行后续的验证和原始方法
              }
            }
          }
        }
        return originalMethod.apply(this, args);  // 所有验证都通过,执行原始方法
      };
    };
  }
  
  @validateParams({
    'a': { objName: 'obj', test: val => val < 100, message: '参数必须小于100' },
    'b': { test: val => val > 0, message: '参数必须大于0' }
  })
  submit(obj,b){obj.a + b}

常用的装饰器-示例

总结

JavaScript装饰器可以使用ES7中的装饰器语法@decorator来声明,也可以使用函数表达式或函数调用形式来定义。

在使用装饰器时需要注意代码的可读性和可维护性,避免过度使用导致代码变得复杂和难以理解。同时,也需要注意装饰器的实现细节和语法规范,以确保代码的正确性和稳定性。

相关推荐
华玥作者14 小时前
[特殊字符] VitePress 对接 Algolia AI 问答(DocSearch + AI Search)完整实战(下)
前端·人工智能·ai
Mr Xu_14 小时前
告别冗长 switch-case:Vue 项目中基于映射表的优雅路由数据匹配方案
前端·javascript·vue.js
前端摸鱼匠14 小时前
Vue 3 的toRefs保持响应性:讲解toRefs在解构响应式对象时的作用
前端·javascript·vue.js·前端框架·ecmascript
lang2015092814 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
好家伙VCC15 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
未来之窗软件服务16 小时前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君
嘿起屁儿整16 小时前
面试点(网络层面)
前端·网络
VT.馒头16 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
phltxy17 小时前
Vue 核心特性实战指南:指令、样式绑定、计算属性与侦听器
前端·javascript·vue.js
Byron070718 小时前
Vue 中使用 Tiptap 富文本编辑器的完整指南
前端·javascript·vue.js