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的实现原理的模拟代码 -4 重要的扩展函数 extend
Aug 03 Javascript
基于jQuery的实现简单的分页控件
Oct 10 Javascript
javascript 数字格式化输出的实现代码
Dec 10 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
Jan 07 Javascript
node.js中的path.isAbsolute方法使用说明
Dec 08 Javascript
浅谈Javascript数组索引
Jul 29 Javascript
基于AngularJS实现页面滚动到底自动加载数据的功能
Oct 16 Javascript
jQuery实现右键菜单、遮罩等效果代码
Sep 27 Javascript
jQuery实现手机版页面翻页效果的简单实例
Oct 05 Javascript
jQuery 1.9版本以上的浏览器判断方法代码分享
Aug 28 jQuery
vue+springboot前后端分离实现单点登录跨域问题解决方法
Jan 30 Javascript
Vue.js实现数据响应的方法
Aug 13 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处理抢购类功能的高并发请求
2018/02/08 PHP
CI框架(CodeIgniter)实现的导入、导出数据操作示例
2018/05/24 PHP
thinkphp集成前端脚手架Vue-cli的教程图解
2018/08/30 PHP
PHP whois查询类定义与用法示例
2019/04/03 PHP
Laravel基础-关于引入公共文件的两种方式
2019/10/18 PHP
用JavaScript实现类似于ListBox功能示例代码
2014/03/09 Javascript
JQuery 给元素绑定click事件多次执行的解决方法
2014/09/09 Javascript
js数组的基本操作(很全自己整理的)
2014/10/16 Javascript
node+express+jade制作简单网站指南
2014/11/26 Javascript
使用ajax+jqtransform实现动态加载select
2014/12/01 Javascript
Jquery中find与each方法用法实例
2015/02/04 Javascript
jQuery实现数秒后自动提交form的方法
2015/03/05 Javascript
使用jQuery制作Web页面遮罩层插件的实例教程
2016/05/26 Javascript
JavaScript学习小结之使用canvas画“哆啦A梦”时钟
2016/07/24 Javascript
js的三种继承方式详解
2017/01/21 Javascript
Angular.JS中指令ng-if的注意事项小结
2017/06/21 Javascript
react 父组件与子组件之间的值传递的方法
2017/09/14 Javascript
vue cli构建的项目中请求代理与项目打包问题
2018/02/26 Javascript
微信小程序wxml列表渲染原理解析
2019/11/27 Javascript
React中Ref 的使用方法详解
2020/04/28 Javascript
[02:16]DOTA2超级联赛专访Burning 逆袭需要抓住机会
2013/06/24 DOTA
[05:03]显微镜下的DOTA2第十期——Ti3豪之超神幽鬼
2014/06/23 DOTA
Python探索之ModelForm代码详解
2017/10/26 Python
使用sklearn进行对数据标准化、归一化以及将数据还原的方法
2018/07/11 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
html5小技巧之通过document.head获取head元素
2014/06/04 HTML / CSS
深入浅析HTML5中的article和section的区别
2018/05/15 HTML / CSS
排序都有哪几种方法?请列举。用JAVA实现一个快速排序
2014/02/16 面试题
浪漫婚礼主持词
2014/03/14 职场文书
体育系毕业生求职自荐信
2014/04/16 职场文书
运动会拉拉队口号
2014/06/09 职场文书
公司领导九九重阳节发言稿2014
2014/09/25 职场文书
golang协程池模拟实现群发邮件功能
2021/05/02 Golang
详解Python requests模块
2021/06/21 Python
利用uni-app生成微信小程序的踩坑记录
2022/04/05 Javascript
golang语言指针操作
2022/04/14 Golang