基于element的区间选择组件

公司的系统中,产品经理在设计时常常要求对某个字段进行区间阈值设置或者做为筛选条件。可是苦于element中没有很是契合的组件(slider组件并不支持两端均能设定),因而本身动手造了一个。javascript

成果

最终的展现效果以下:html

clipboard.png

需求

这里以项目的需求为例,基本的需求以下:前端

  1. 分为左右值,包含左右值,正整数
  2. 左侧必须大于等于1,右侧不得大于100000,右侧值必须不小于左侧
  3. 默认:左侧20,右侧100000,均必填
  4. 失焦校验

页面和表单校验结构同样:java

<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>

主要思路

  1. 单个表单校验:必填项校验、正整数校验、区间校验
  2. 关联校验:右侧阈值不得小于左侧阈值

根据上面的思路,单个表单的校验属于公共校验方法,关联校验须要分别校验(由于对比对象不一样,且提示语不一样),由此在自定义校验中有了以下定义:segmentfault

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' },
    ],
},

公共校验方法:正整数校验、区间校验promise

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输出的始终是字符串类型,须要转换成数字后进行比对前端工程师

关联校验:ide

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!如今真正的坑才开始ui

填坑(重点)

根据上面的写法,组件的基本功能实现了,可是有一个坑!以下:
clipboard.pngthis

很显然,左侧值是小于右侧值的,可是校验提示仍然报错。究其缘由,仍是关联校验的问题。既然是关联交验,改变其中一个时应该会从新校验两个。很简单,在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();
},

总结

  1. input表单输出值为String类型,即便设置了type=number
  2. 关联交验时须要验证其关联项,且不能重复校验

源码连接

相关文章
相关标签/搜索