业务描述
因为涉及了目前进行的项目,描述下简单的业务。有2个需求,如下:
- 根据用户输入的1个值计算另外2个值,需要校验用户输入值的个数,并提示用户在计算公式中只能输入1个值.类似于f(z)=ax,f(y)=bx.
- 根据用户输入的2个值计算另外1个值,需要校验用户输入的值的个数,并提示用户在计算公式中必须输入任意2个值.类似于f(x,y)=az,求z.
实现
表单
因为每个表单需要单独验证且返回信息不同,所以采用了自定义规则校验表单,同时重置表单均使用element-ui中的方式.具体可以参考element-ui的文档.
计算公式
计算公式方式使用了ES5的js方式,在vue里直接定义一个js文件,将每一个公式定义成一个属性,最后通过call的方式来调用.示例代码如下:
这里比如定义了公式例子如下:
const formulae = {
formulae1: function() {
...
},
formulae2: function() {
...
},
formulae3: function() {
...
}
};
export default formulae ;
前端调用计算公式思路
在前段直接将计算公式import进来,假设定为formulae.根据用户输入的属性,获取对应的公式然后进行调用.最终需要调用的方式如下
import formulae from "xxx";
formulae.计算公式对象中的对应的属性.call(obj)//或formulae[计算公式对象中的对应的属性].call(obj) obj为用户输入的表单的对象
由于需要根据从用户输入端获取属性并找到相应的公式,所以这里定义了一个json对象(这里的实现不太好,需要改进),页面用户数输入的属性为key,计算公式的属性名为value,示例如下:
const ruleObj= {
userInputProp1: "formulae1",
userInputProp2: "formulae2",
userInputProp3: "formulae3",
};
这里有1个问题,就是对于需求2,当有2个属性时无法直接用属性名,所以在后续校验的时候对有值的属性进行了一个排序,已这个排序数组的toString值作为key,指定对应的公式.
前端获取用户输入的属性及个数校验
获取用户输入的对象时,因为对象绑定了form的model属性,所以直接通过this.$refs[formName].model的方式取得对应的对象.之后需要校验该对象中有值的属性的个数与期望的是否一致,在需求1中需要1个值,需求2里需要判断输入的是否是2个值,代码如下:
/**
* 校验对象中必须有值的属性值个数与期望有值的属性的个数是否一致
* params:
* checkForm:需要校验的对象
* checkPropsNum:期望校验的输入的属性值个数
*/
checkSubmitForm(checkForm, checkPropsNum) {
if (
Object.values(checkForm).filter(item => item).length !== checkPropsNum
) {
this.$message.success("请在" + checkPropsNum + "个输入框中输入任意值!");
} else {
return true;
}
return false;
}
校验用户输入的属性值个数后,需要获得这些有值的属性,并根据属性名调用对应的公式,因为要用此值作为key,所以返回是进行了对数组的排序.获取有值的属性数组如下:
/**
* 获取对象中有值的属性
* params:
* form:期望校验的对象
* return:
* category:对象中已输入值的属性,并排序
*/
handleSubmitCategory(form) {
let category = [];
Object.keys(form).forEach(function(item) {
if ("" != form[item] && form[item].length > 0) {
category.push(item);
} else {
form[item] = 0;
}
});
return category.sort();
}
此时,有值的对象已经取到,所以只需要校验表单正确后(参考element-ui中 this.(refs[formName].validate()的方式),直接调用formulae[ruleObj[有值属性的数组.toString()]].call(this.)refs[formName].model)即可。
另2种思路
- 因为在ES6里已经不建议直接使用call的方式,对于初学者class的方式更容易理解,所以可以在公式部分使用class来定义,并根据传入的参数来判断调用的公式,这里省略以后在继续改.
- vue里的watch深度监听可以监听对象下属性的变化,所以也可以使用watch的方式来实现.但是在需求2里的时候需要判断2个属性,所以需要在监听中进行特殊的处理.也不难.