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 相关文章推荐
得到文本框选中的文字,动态插入文字的js代码
Mar 07 Javascript
常用Extjs工具:Extjs.util.Format使用方法
Mar 22 Javascript
jquery创建并行对象或者合并对象的实现代码
Oct 10 Javascript
将数字转换成大写的人民币表达式的js函数
Sep 21 Javascript
Javascript基础教程之函数对象和属性
Jan 18 Javascript
JQuery中绑定事件(bind())和移除事件(unbind())
Feb 27 Javascript
Javascript中prototype属性实现给内置对象添加新的方法
May 14 Javascript
一系列Bootstrap导航条使用方法分享
Apr 29 Javascript
Angularjs 创建可复用组件实例代码
Oct 09 Javascript
AngularJS表格添加序号的方法
Mar 03 Javascript
javascript 跨域问题以及解决办法
Jul 17 Javascript
vue脚手架项目创建步骤详解
Mar 02 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
【COS正片】蕾姆睡衣cos,纯洁可爱被治愈了 cn名濑弥七
2020/03/02 日漫
php对称加密算法示例
2014/05/07 PHP
客户端静态页面玩分页
2006/06/26 Javascript
nodejs开发环境配置与使用
2014/11/17 NodeJs
jQuery EasyUI Dialog拖不下来如何解决
2015/09/28 Javascript
jQuery插件实现适用于移动端的地址选择器
2016/02/18 Javascript
jQuery插件AjaxFileUpload实现ajax文件上传
2016/05/05 Javascript
dul无法加载bootstrap实现unload table/user恢复
2016/09/29 Javascript
jquery 动态增加删除行的简单实例(推荐)
2016/10/12 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
2017/02/10 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
2017/06/19 Javascript
webpack开发跨域问题解决办法
2017/08/03 Javascript
使用Bootstrap和Vue实现用户信息的编辑删除功能
2017/10/25 Javascript
vue实现倒计时获取验证码效果
2020/04/17 Javascript
JS实现灯泡开关特效
2020/03/30 Javascript
JavaScript实现图片放大预览效果
2020/11/02 Javascript
简单介绍Python2.x版本中的cmp()方法的使用
2015/05/20 Python
Python 提取dict转换为xml/json/table并输出的实现代码
2016/08/28 Python
Python+selenium 获取一组元素属性值的实例
2018/06/22 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
2019/05/04 Python
python3 tkinter实现添加图片和文本
2019/11/26 Python
wxpython自定义下拉列表框过程图解
2020/02/14 Python
Python中的Cookie模块如何使用
2020/06/04 Python
Python调用百度OCR实现图片文字识别的示例代码
2020/07/17 Python
销售所有的狗狗产品:Dog.com
2016/10/13 全球购物
英国家居用品和床上用品零售商:P&B Home
2020/01/16 全球购物
建筑实习自我鉴定
2013/10/18 职场文书
校园安全演讲稿
2014/05/09 职场文书
五好关工委申报材料
2014/05/31 职场文书
医院党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
欢迎词范文
2015/01/27 职场文书
公司内部升职自荐信
2015/03/27 职场文书
JS新手入门数组处理的实用方法汇总
2021/04/07 Javascript
Python 实现Mac 屏幕截图详解
2021/10/05 Python
MySQL学习之基础命令实操总结
2022/03/19 MySQL
MySql如何将查询的出来的字段进行转换
2022/06/14 MySQL