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 相关文章推荐
关于图片的预加载过程中隐藏未知的
Dec 19 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
May 08 Javascript
jQuery中prepend()方法用法实例
Dec 25 Javascript
基于JS实现密码框(password)中显示文字提示功能代码
May 27 Javascript
js基于cookie记录来宾姓名的方法
Jul 19 Javascript
JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()
Aug 11 Javascript
js 获取本地文件及目录的方法(推荐)
Nov 10 Javascript
Angularjs实现分页和分页算法的示例代码
Dec 23 Javascript
JS实现移动端按首字母检索城市列表附源码下载
Jul 05 Javascript
微信小程序实时聊天WebSocket
Jul 05 Javascript
vue.js的vue-cli脚手架中使用百度地图API的实例
Jan 21 Javascript
如何使用JavaScript检测空闲的浏览器选项卡
May 28 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
用户的详细注册和判断
2006/10/09 PHP
php中计算时间差的几种方法
2009/12/31 PHP
php数组函数序列之krsort()- 对数组的元素键名进行降序排序,保持索引关系
2011/11/02 PHP
PHP类的自动加载机制实现方法分析
2019/01/10 PHP
ie 调试javascript的工具
2009/04/29 Javascript
JS:window.onload的使用介绍
2013/11/13 Javascript
JS实现两个大数(整数)相乘
2014/04/28 Javascript
node.js中的fs.readSync方法使用说明
2014/12/17 Javascript
JavaScript日期时间与时间戳的转换函数分享
2015/01/31 Javascript
在JavaScript中模拟类(class)及类的继承关系
2016/05/20 Javascript
js正则表达式replace替换变量方法
2016/05/21 Javascript
Node.js 实现简单小说爬虫实例
2016/11/18 Javascript
AngularJs表单校验功能实例代码
2017/02/09 Javascript
Vue之Watcher源码解析(1)
2017/07/19 Javascript
jQuery实现的鼠标响应缓冲动画效果示例
2018/02/13 jQuery
vue项目首屏加载时间优化实战
2019/04/23 Javascript
atom-design(Vue.js移动端组件库)手势组件使用教程
2019/05/16 Javascript
Vue.js中的组件系统
2019/05/30 Javascript
js实现类选择器和name属性选择器的示例步骤
2021/02/07 Javascript
matplotlib.pyplot画图 图片的二进制流的获取方法
2018/05/24 Python
Python 实现「食行生鲜」签到领积分功能
2018/09/26 Python
python标准库os库的函数介绍
2020/02/12 Python
python中数据库like模糊查询方式
2020/03/02 Python
Django高并发负载均衡实现原理详解
2020/04/04 Python
Python+Opencv实现把图片、视频互转的示例
2020/12/17 Python
One.com挪威:北欧成长最快的网络托管公司
2016/11/19 全球购物
全球性的在线时尚男装零售商:boohooMAN
2016/12/17 全球购物
葡萄牙航空官方网站:TAP Air Portugal
2019/10/31 全球购物
大学校园活动策划书
2014/02/04 职场文书
人事文员岗位职责
2014/02/16 职场文书
《长城和运河》教学反思
2014/04/14 职场文书
Python3接口性能测试实例代码
2021/06/20 Python
数据库之SQL技巧整理案例
2021/07/07 SQL Server
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers
CentOS 7安装mysql5.7使用XtraBackUp备份工具命令详解
2022/04/12 MySQL
Nginx 匹配方式
2022/05/15 Servers