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 相关文章推荐
解决Jquery load()加载GB2312页面时出现乱码的两种方案
Sep 10 Javascript
浅析JavaScript中的类型和对象
Nov 29 Javascript
JavaScript中的操作符==与===介绍
Dec 31 Javascript
JS控制弹出新页面窗口位置和大小的方法
Mar 02 Javascript
jQuery实现的向下图文信息滚动效果
May 03 Javascript
AngularJS 中的事件详解
Jul 28 Javascript
Bootstrap框架的学习教程详解(二)
Oct 18 Javascript
js自定义Tab选项卡效果
Jun 05 Javascript
JS实现的加减乘除四则运算计算器示例
Aug 09 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
Aug 19 Javascript
ES6新增的数组知识实例小结
May 23 Javascript
javascript之Object.assign()的痛点分析
Mar 03 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
在windows iis5下安装php4.0+mysql之我见
2006/10/09 PHP
使用PHP强制下载PDF文件示例
2014/01/17 PHP
PHP 导出Excel示例分享
2014/08/18 PHP
php简单获取目录列表的方法
2015/03/24 PHP
Zend Framework分发器用法示例
2016/12/11 PHP
实例说明js脚本语言和php脚本语言的区别
2019/04/04 PHP
jQuery-onload让第一次页面加载时图片是淡入方式显示
2012/05/23 Javascript
js+JQuery返回顶部功能如何实现
2012/12/03 Javascript
js replace正则表达式应用案例讲解
2013/01/17 Javascript
Javascript的无new构建实例详解
2016/05/15 Javascript
全面解析jQuery $(document).ready()和JavaScript onload事件
2016/06/08 Javascript
Bootstrap CSS组件之输入框组
2016/12/17 Javascript
ES6新特性之Object的变化分析
2017/03/31 Javascript
JQuery Ajax 异步操作之动态添加节点功能
2017/05/24 jQuery
使用watch监听路由变化和watch监听对象的实例
2018/02/24 Javascript
layer弹出层 iframe层去掉滚动条的实例代码
2018/08/17 Javascript
10分钟彻底搞懂Http的强制缓存和协商缓存(小结)
2018/08/30 Javascript
详解Vue项目中实现锚点定位
2019/04/24 Javascript
sortable+element 实现表格行拖拽的方法示例
2019/06/07 Javascript
VueJS 取得 URL 参数值的方法
2019/07/19 Javascript
vue 地区选择器v-distpicker的常用功能
2019/07/23 Javascript
Python封装shell命令实例分析
2015/05/05 Python
python替换字符串中的子串图文步骤
2019/06/19 Python
Pytorch实现LSTM和GRU示例
2020/01/14 Python
python GUI库图形界面开发之PyQt5窗口背景与不规则窗口实例
2020/02/25 Python
python如何求100以内的素数
2020/05/27 Python
python如何实现读取并显示图片(不需要图形界面)
2020/07/08 Python
Python全局变量与global关键字常见错误解决方案
2020/10/05 Python
如何通过python实现IOU计算代码实例
2020/11/02 Python
python switch 实现多分支选择功能
2020/12/21 Python
把富文本的回车转为br标签
2019/08/09 HTML / CSS
Helly Hansen工作服美国官方网上商店:为最恶劣的环境
2019/09/04 全球购物
大学生演讲稿范文
2014/01/11 职场文书
用Python制作灯光秀短视频的思路详解
2021/04/13 Python
Python使用Kubernetes API访问集群
2021/05/30 Python
Java实现简易的分词器功能
2021/06/15 Java/Android