从接触到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
来声明,也可以使用函数表达式或函数调用形式来定义。
在使用装饰器时需要注意代码的可读性和可维护性,避免过度使用导致代码变得复杂和难以理解。同时,也需要注意装饰器的实现细节和语法规范,以确保代码的正确性和稳定性。