vue基于element的区间选择组件


Posted in Javascript onSeptember 07, 2018

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

成果

最终的展示效果如下:

vue基于element的区间选择组件

需求

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

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

页面和表单校验结构一样:

<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. 关联校验:右侧阈值不得小于左侧阈值

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

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!现在真正的坑才开始

填坑(重点)

根据上面的写法,组件的基本功能实现了,但是有一个坑!如下:

vue基于element的区间选择组件

很显然,左侧值是小于右侧值的,但是校验提示仍然报错。究其原因,还是关联校验的问题。既然是关联交验,改变其中一个时应该会重新校验两个。很简单,在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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
加载 Javascript 最佳实践
Oct 30 Javascript
JavaScript常用全局属性与方法记录积累
Jul 03 Javascript
Javascript模块化编程详解
Dec 01 Javascript
使用jQuery管理选择结果
Jan 20 Javascript
Bootstrap嵌入jqGrid,使你的table牛逼起来
May 05 Javascript
jQuery实现checkbox列表的全选、反选功能
Nov 24 Javascript
解决Vue2.x父组件与子组件之间的双向绑定问题
Mar 06 Javascript
js中split()方法得到的数组长度问题
Jul 19 Javascript
详解Vue开发微信H5微信分享签名失败问题解决方案
Aug 09 Javascript
在Vue项目中使用snapshot测试的具体使用
Apr 16 Javascript
小程序调用微信支付的方法
Sep 26 Javascript
js实现页面图片消除效果
Mar 24 Javascript
vue-cli监听组件加载完成的方法
Sep 07 #Javascript
原生JS实现DOM加载完成马上执行JS代码的方法
Sep 07 #Javascript
vue加载完成后的回调函数方法
Sep 07 #Javascript
使用vue-router与v-if实现tab切换遇到的问题及解决方法
Sep 07 #Javascript
VUE DOM加载后执行自定义事件的方法
Sep 07 #Javascript
详解JavaScript事件循环机制
Sep 07 #Javascript
解决vue 引入子组件报错的问题
Sep 06 #Javascript
You might like
解决php中Cannot send session cache limiter 的问题的方法
2007/04/27 PHP
怎样给PHP源代码加密?PHP二进制加密与解密的解决办法
2013/04/22 PHP
php echo, print, print_r, sprintf, var_dump, var_expor的使用区别
2013/06/20 PHP
PHP面向对象程序设计之类常量用法实例
2014/08/20 PHP
PHP实现简单实用的分页类代码
2016/04/08 PHP
PHP替换Word中变量并导出PDF图片的实现方法
2020/11/26 PHP
document.documentElement的一些使用技巧
2013/04/18 Javascript
jQuery实现点击后标记当前菜单位置(背景高亮菜单)效果
2015/08/22 Javascript
深入理解JS函数的参数(arguments)的使用
2016/05/28 Javascript
用js读写cookie的简单方法(推荐)
2016/08/08 Javascript
用AngularJS来实现监察表单按钮的禁用效果
2016/11/02 Javascript
基于jQuery实现的打字机效果
2017/01/16 Javascript
React Native如何消除启动时白屏的方法
2017/08/08 Javascript
jquery获取链接地址和跳转详解(推荐)
2017/08/15 jQuery
JS库之ParticlesJS使用简介
2017/09/12 Javascript
Vue.set()实现数据动态响应的方法
2018/02/07 Javascript
移动端图片上传旋转、压缩问题的方法
2018/10/16 Javascript
详解JavaScript中的数据类型,以及检测数据类型的方法
2020/09/17 Javascript
Python里隐藏的“禅”
2014/06/16 Python
Python内置函数dir详解
2015/04/14 Python
详细解读Python的web.py框架下的application.py模块
2015/05/02 Python
Python2.x中文乱码问题解决方法
2015/06/02 Python
Python+OpenCV图片局部区域像素值处理改进版详解
2019/01/23 Python
python opencv 检测移动物体并截图保存实例
2020/03/10 Python
解决python中import文件夹下面py文件报错问题
2020/06/01 Python
python实现数据结构中双向循环链表操作的示例
2020/10/09 Python
python获取命令行参数实例方法讲解
2020/11/02 Python
selenium设置浏览器为headless无头模式(Chrome和Firefox)
2021/01/08 Python
一些Solaris面试题
2013/03/22 面试题
保护环境倡议书500字
2014/05/19 职场文书
标准版离职证明书
2014/09/12 职场文书
部队反四风对照检查材料
2014/09/26 职场文书
小学家长通知书评语
2014/12/31 职场文书
2015年司机年终工作总结
2015/05/14 职场文书
初婚未育证明样本
2015/06/18 职场文书
企业反腐倡廉心得体会
2015/08/15 职场文书