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 版本]
Mar 20 Javascript
FireFox JavaScript全局Event对象
Jun 14 Javascript
Prototype PeriodicalExecuter对象 学习
Jul 19 Javascript
灵活应用js调试技巧解决样式问题的步骤分享
Mar 15 Javascript
jquery中post方法用法实例
Oct 21 Javascript
AngularJS入门教程之AngularJS表达式
Apr 18 Javascript
总结在前端排序中遇到的问题
Jul 19 Javascript
原生js实现中奖信息无间隙滚动效果
Jan 18 Javascript
JavaScript正则表达式和级联效果
Sep 14 Javascript
基于twbsPagination.js分页插件使用心得(分享)
Oct 21 Javascript
vue插件实现v-model功能
Sep 10 Javascript
使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)
Jun 09 Vue.js
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
php5编程中的异常处理详细方法介绍
2008/07/29 PHP
关于PHP内存溢出问题的解决方法
2013/06/25 PHP
php实现根据字符串生成对应数组的方法
2014/09/22 PHP
php中使用url传递数组的方法
2015/02/11 PHP
php使用ftp远程上传文件类(完美解决主从文件同步问题的方法)
2016/09/23 PHP
PHP中rename()函数的妙用讲解
2019/02/28 PHP
简介AngularJS中使用factory和service的方法
2015/06/17 Javascript
jquery控制页面部分刷新的方法
2015/06/24 Javascript
js计算文本框输入的字符数
2015/10/23 Javascript
Bootstrap模块dropdown实现下拉框响应
2016/05/22 Javascript
jquery 实现滚动条下拉时无限加载的简单实例
2016/06/01 Javascript
基于原生JS实现图片裁剪
2016/08/01 Javascript
jQuery插件HighCharts绘制2D柱状图、折线图和饼图的组合图效果示例【附demo源码下载】
2017/03/09 Javascript
浅谈React中的元素、组件、实例和节点
2018/02/27 Javascript
解决vue-cli脚手架打包后vendor文件过大的问题
2018/09/27 Javascript
详解JavaScript 新语法之Class 的私有属性与私有方法
2019/04/23 Javascript
微信小程序自定义toast组件的方法详解【含动画】
2019/05/11 Javascript
vue路由插件之vue-route
2019/06/13 Javascript
Python获取Windows或Linux主机名称通用函数分享
2014/11/22 Python
使用Python的判断语句模拟三目运算
2015/04/24 Python
通过Py2exe将自己的python程序打包成.exe/.app的方法
2018/05/26 Python
TensorFlow 合并/连接数组的方法
2018/07/27 Python
对python打乱数据集中X,y标签对的方法详解
2018/12/14 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
python3的数据类型及数据类型转换实例详解
2019/08/20 Python
打包PyQt5应用时的注意事项
2020/02/14 Python
XD健身器材:Kevlar球、Crossfit健身球
2019/03/26 全球购物
数字天堂软件测试面试题
2012/12/23 面试题
会计系毕业个人自荐信格式
2013/09/23 职场文书
咨询公司各岗位职责
2013/12/02 职场文书
企业为何需要商业计划书
2013/12/26 职场文书
乡镇干部先进性教育活动个人整改措施
2014/09/16 职场文书
资料员岗位职责
2015/02/10 职场文书
转学证明范本
2015/06/19 职场文书
2015年评职称个人工作总结
2015/10/15 职场文书
Win11 S Mode版本泄露 正式上线后叫做Windows 11 SE
2021/11/21 数码科技