时间:2021-05-26
公司的系统中,产品经理在设计时经常要求对某个字段进行区间阈值设置或者作为筛选条件。但是苦于element中没有非常契合的组件(slider组件并不支持两端均能设定),于是自己动手造了一个。
成果
最终的展示效果如下:
需求
这里以项目的需求为例,基本的需求如下:
页面和表单校验结构一样:
<el-form ref="form" :model="form" :rules="rules"> <el-form-item prop="min"> <el-input v-model="form.min" /> </el-form-item> ~ <el-form-item prop="max"> <el-input v-model="form.max" /> </el-form-item></el-form>主要思路
根据上面的思路,单个表单的校验属于公共校验方法,关联校验需要分别校验(因为对比对象不同,且提示语不同),由此在自定义校验中有了如下定义:
rules: { min: [ { required: true, message: '必填项,请维护', trigger: 'blur' }, { validator: this.validateCom, trigger: 'blur' }, { validator: this.validateMin, trigger: 'blur' }, ], max: [ { required: true, message: '必填项,请维护', trigger: 'blur' }, { validator: this.validateCom, trigger: 'blur' }, { validator: this.validateMax, trigger: 'blur' }, ],},公共校验方法:正整数校验、区间校验
validateCom(rule, value, callback) { const one = Number(value); if (Number.isInteger(one)) { if (one < MIN_NUMBER) { return callback(new Error(`输入值必须大于${MIN_NUMBER}`)); } else if (one > MAX_NUMBER) { return callback(new Error(`输入值必须小于${MAX_NUMBER}`)); } return callback(); } return callback(new Error('输入值必须为正整数'));},注意:input输出的始终是字符串类型,需要转换成数字后进行比对
关联校验:
validateMin(rule, value, callback) { const one = Number(value); const max = Number(this.form.max); if (!max || one < max) { return callback(); } return callback(new Error('输入值不得大于最大阈值'));},validateMax(rule, value, callback) { const one = Number(value); const min = Number(this.form.min); if (!min || one > min) { return callback(); } return callback(new Error('输入值不得小于最小阈值'));},大概,你会想,这不就完了吗!so easy!现在真正的坑才开始
填坑(重点)
根据上面的写法,组件的基本功能实现了,但是有一个坑!如下:
很显然,左侧值是小于右侧值的,但是校验提示仍然报错。究其原因,还是关联校验的问题。既然是关联交验,改变其中一个时应该会重新校验两个。很简单,在input改变时,重新校验表单不就OK了吗
handleChange() { this.$refs.form.validate();}真实表现正如我们所料,但是当我们打开console的时候,会看到Uncaught (in promise) false,这又是什么鬼,身为优秀的前端工程师,你定不会允许自己的代码里报错,即使不影响正常流程。
经查证:Promise报错,Uncaught的意思是代表有reject状态没有被catch。究其原因,改变一个值时,校验整个表单时,改变的那个input会执行两次校验,导致异常。
最后做如下修改:
handleMinChange() { this.$refs.form.validateField('max');},handleMaxChange() { this.$refs.form.validateField('min');},// 并对外暴露操作方法getFormData() { const ret = {}; this.$refs.form.validate((valid) => { ret.valid = valid; ret.form = this.form; }); return ret;},resetForm() { this.$refs.form.resetFields();},总结input表单输出值为String类型,即使设置了type=number关联交验时需要验证其关联项,且不能重复校验
全部代码:
<template> <el-form ref="form" :model="form" :rules="rules"> <el-form-item prop="min"> <el-input v-model="form.min" @change="handleMinChange" /> </el-form-item> ~ <el-form-item prop="max"> <el-input v-model="form.max" @change="handleMaxChange" /> </el-form-item> </el-form></template> <script>const MIN_NUMBER = 1;const MAX_NUMBER = 100000; export default { data() { return { form: { min: '20', max: '100000' }, rules: { min: [ { required: true, message: '必填项,请维护', trigger: 'blur' }, { validator: this.validateCom, trigger: 'blur' }, { validator: this.validateMin, trigger: 'blur' }, ], max: [ { required: true, message: '必填项,请维护', trigger: 'blur' }, { validator: this.validateCom, trigger: 'blur' }, { validator: this.validateMax, trigger: 'blur' }, ], }, }; }, methods: { getFormData() { const ret = {}; this.$refs.form.validate((valid) => { ret.valid = valid; ret.form = this.form; }); return ret; }, resetForm() { this.$refs.form.resetFields(); }, handleMinChange() { this.$refs.form.validateField('max'); }, handleMaxChange() { this.$refs.form.validateField('min'); }, validateCom(rule, value, callback) { const one = Number(value); if (Number.isInteger(one)) { if (one < MIN_NUMBER) { return callback(new Error('输入值必须大于0')); } else if (one > MAX_NUMBER) { return callback(new Error('输入值必须小于100000')); } return callback(); } return callback(new Error('输入值必须为正整数')); }, validateMin(rule, value, callback) { const one = Number(value); const max = Number(this.form.max); if (!max || one < max) { return callback(); } return callback(new Error('输入值不得大于最大阈值')); }, validateMax(rule, value, callback) { const one = Number(value); const min = Number(this.form.min); if (!min || one > min) { return callback(); } return callback(new Error('输入值不得小于最小阈值')); }, },};</script>以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
在vue2.0中引用element-ui组件库element-ui是由饿了么团队开发的一套基于Vue2.0的桌面端组件库。官网:http://element.e
calendarvue日期选择组件一个选择日期的vue组件基于vue2.0+vuex原本是想找这样的一个组件的,查看了vuex后,发现vuex的写法还不是基于2
前言vue.js的UI组件库,在git上有多个项目,我见的使用者比较多的是iView和Element.两个组件库,组件都很丰富。官网的介绍iView:一套基于V
原因:autofocus是vue中input的原生属性,element也支持这种方法,但是element中的el-input组件外面还有其他组件,导致autof
现在基于vue的UI组件库有很多,比如iview,element-ui等。但有时候这些组件库满足不了我们的开发需求,这时候我们就需要自己写一个插件。举第一个栗子