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 相关文章推荐
iframe 上下滚动条如何默认在下方实现原理
Dec 10 Javascript
javascript实现画不相交的圆
Apr 07 Javascript
JavaScript汉诺塔问题解决方法
Apr 21 Javascript
javascript日期格式化方法汇总
Oct 04 Javascript
解析Node.js基于模块和包的代码部署方式
Feb 16 Javascript
js实现select二级联动下拉菜单
Apr 17 Javascript
JS中取二维数组中最大值的方法汇总
Apr 17 Javascript
JavaScript跨域调用基于JSON的RESTful API
Jul 09 Javascript
Vue.js搭建移动端购物车界面
Jun 28 Javascript
说说Vuex的getters属性的具体用法
Apr 15 Javascript
从零搭一个自用的前端脚手架的方法步骤
Sep 23 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
Apr 08 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实现Linux服务器木马排查及加固功能
2014/12/29 PHP
Yii2框架中一些折磨人的坑
2019/12/15 PHP
javascript中的对象和数组的应用技巧
2007/01/07 Javascript
优化网页之快速的呈现我们的网页
2007/06/29 Javascript
基于jQuery的简单的列表导航菜单
2011/03/02 Javascript
js 火狐下取本地路径实现思路
2013/04/02 Javascript
使用javascript实现ListBox左右全选,单选,多选,全请
2013/11/07 Javascript
js导航栏单击事件背景变换示例代码
2014/01/13 Javascript
Javascript排序算法之合并排序(归并排序)的2个例子
2014/04/04 Javascript
js实现密码强度检测【附示例】
2016/03/30 Javascript
picLazyLoad 实现图片延时加载(包含背景图片)
2016/07/21 Javascript
AngularJS过滤器filter用法实例分析
2016/11/04 Javascript
JavaScript常见的五种数组去重的方式
2016/12/15 Javascript
JS+H5 Canvas实现时钟效果
2018/07/20 Javascript
解决vue打包css文件中背景图片的路径问题
2018/09/03 Javascript
原生js实现自定义滚动条组件
2021/01/20 Javascript
Python基于回溯法子集树模板解决马踏棋盘问题示例
2017/09/11 Python
python批量识别图片指定区域文字内容
2019/04/30 Python
Python基于机器学习方法实现的电影推荐系统实例详解
2019/06/25 Python
pytorch实现从本地加载 .pth 格式模型
2020/02/14 Python
Python数组并集交集补集代码实例
2020/02/18 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
详解CSS3的box-shadow属性制作边框阴影效果的方法
2016/05/10 HTML / CSS
在加拿大在线租赁和购买电子游戏:Game Access
2019/09/02 全球购物
意大利香水和化妆品购物网站:Parfimo.it
2019/10/06 全球购物
马来西亚奢侈品牌购物商城:Valiram 247
2020/09/29 全球购物
信息专业本科生个人的自我评价
2013/10/28 职场文书
建筑工程技术应届生求职信
2013/11/17 职场文书
接待员岗位责任制
2014/02/10 职场文书
房屋鉴定委托书范本
2014/09/23 职场文书
怎样写离婚协议书
2015/01/26 职场文书
餐厅保洁员岗位职责
2015/04/10 职场文书
节约用水广告语60条
2019/11/14 职场文书
MySQL创建管理RANGE分区
2022/04/13 MySQL
让JavaScript代码更加精简的方法技巧
2022/06/01 Javascript
nginx七层负载均衡配置详解
2022/07/15 Servers