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 Split方法,indexOf方法、lastIndexOf 方法和substring 方法
Mar 21 Javascript
jQuery创建自己的插件(自定义插件)的方法
Jun 10 Javascript
innerText 使用示例
Jan 23 Javascript
js显示当前日期时间和星期几
Oct 22 Javascript
JavaScript基于自定义函数判断变量类型的实现方法
Nov 23 Javascript
JavaScript中英文字符长度统计方法示例【按照中文占2个字符】
Jan 17 Javascript
Bootstrap组合上、下拉框简单实现代码
Mar 06 Javascript
JavaScript实现反转字符串的方法详解
Apr 27 Javascript
微信小程序修改swiper默认指示器样式的实例代码
Jul 18 Javascript
vue项目添加多页面配置的步骤详解
May 22 Javascript
富文本编辑器vue2-editor实现全屏功能
May 26 Javascript
vue-父子组件和ref实例详解
Nov 10 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实现的在线人员函数库
2008/04/09 PHP
PHP学习笔记 用户注册模块用户类以及验证码类
2011/09/20 PHP
php利用腾讯ip分享计划获取地理位置示例分享
2014/01/20 PHP
php获取YouTube视频信息的方法
2015/02/11 PHP
浅谈php7的重大新特性
2015/10/23 PHP
php通过淘宝API查询IP地址归属等信息
2015/12/25 PHP
YII框架中使用memcache的方法详解
2017/08/02 PHP
PHP PDOStatement::errorInfo讲解
2019/01/31 PHP
msn上的tab功能Firefox对childNodes处理的一个BUG
2008/01/21 Javascript
javascript 获取图片颜色
2009/04/05 Javascript
jQuery get和post 方法传值注意事项
2009/11/03 Javascript
jQuery Ajax方法调用 Asp.Net WebService 的详细实例代码
2011/04/27 Javascript
关于使用 jBox 对话框的提交不能弹出问题解决方法
2012/11/07 Javascript
分享9个最好用的JavaScript开发工具和代码编辑器
2015/03/24 Javascript
jquery事件绑定解绑机制源码解析
2016/09/19 Javascript
vuejs父子组件通信的问题
2017/01/11 Javascript
javascript构造函数以及原型对象的理解
2017/01/13 Javascript
深入理解node.js之path模块
2017/05/03 Javascript
AngularJS使用ui-route实现多层嵌套路由的示例
2018/01/10 Javascript
JS实现运动缓冲效果的封装函数示例
2018/02/18 Javascript
JS实现json对象数组按对象属性排序操作示例
2018/05/18 Javascript
[03:01]2014DOTA2国际邀请赛 DC:我是核弹粉,为Burning和国土祝福
2014/07/13 DOTA
图解Python变量与赋值
2018/04/03 Python
python tkinter图形界面代码统计工具(更新)
2019/09/18 Python
python3注册全局热键的实现
2020/03/22 Python
Python爬虫爬取、解析数据操作示例
2020/03/27 Python
《小熊住山洞》教学反思
2014/02/21 职场文书
大学生社会实践自我鉴定
2014/03/24 职场文书
班主任与学生安全责任书
2014/07/25 职场文书
2014年前台文员工作总结
2014/12/08 职场文书
先进教师事迹材料
2014/12/16 职场文书
2014年电信员工工作总结
2014/12/19 职场文书
七年级上册语文教学计划
2015/01/22 职场文书
女人创业励志语录,句句蕴含能量,激发你的潜能
2019/08/20 职场文书
选购到合适的激光打印机
2022/04/21 数码科技
详细介绍Next.js脚手架完整搭建封装
2022/04/26 Javascript