vant(ZanUi)结合async-validator实现表单验证的方法


Posted in Javascript onDecember 06, 2018

最近在开发一个移动端商城项目,用到了有赞的 vant ,因为最近大都采用 element ui 在做PC端的东西,对比来说,vant的完成度还是偏低了点,很多细节都虽然都实现了接口,但是想使用得自己去想办法,没办法拿来即用。昨天用到 Uploader 图片上传 如是,提供了file回调,却没有提供上传功能,我必须给他加2个函数实现axios提交才能用,还有今天用到表单验证这块,它的 Field组件 虽然给了error-message的错误提示接口,但是没有内置表单验证功能。

element ui 采用async-validator 实现表单验证,我也基于这个组件进行扩展,async-validator不支持细粒化验证,于是先对它进行扩展

validator.js

import asyncValidator from 'async-validator'

class validator {
 /**
 * 构造
 * @param rules object async-validator rules
 * @param data 初始对象
 */
 constructor(rules, data) {
 this.setData(data);
 this.setRules(rules);
 }

 /**
 * 重新定义初始对象
 * 也可以直接修改实例的data
 * validator.data = newData
 * @param data
 */
 setData(data) {
 this.data = data;
 }

 /**
 * 设定规则
 * @param rules rules object async-validator rules
 * @param cover 是否替换旧规则
 */
 setRules(rules, {cover} = {}) {
 if (cover === undefined || cover) {
  this.validators = {};
 }
 for (let attr in rules) {
  const rule = {};
  rule[attr] = rules[attr];
  this.validators[attr] = new asyncValidator(rule);
 }
 }

 /**
 * 执行验证
 * @param callback(errors, fields)
 * @param data 可选 传空将验证构造data 传string或数组验证构造data的响应字段
 * 以上参数顺序可互转
 */
 validate(callback, data) {
 let cb,d;
 if (typeof callback === 'function' ){
  cb = callback;
  d = data;
 }else if (typeof data === 'function' ){
  cb = data;
  d = callback;
 }

 let _d = d;

 if (this.data) {
  if (!d) {
  _d = this.data;
  } else if (typeof d === 'string') {
  _d = {};
  _d[d] = this.data[d]
  } else if (Array.isArray(d)) {
  _d = {};
  d.forEach(attr => {
   _d[attr] = this.data[attr]
  })
  }
 }

 const err = [];

 if (_d) {
  for (let attr in _d) {
  if (this.validators[attr]) {
   const o = {};
   o[attr] = _d[attr];
   this.validators[attr].validate(o, (error) => {
   if (error) {
    err.push(error[0])
   }
   })
  }
  }
 }

 cb && cb(err.length > 0, err)

 }
}

export default function (rules, data) {
 return new validator(rules, data)
}

demo.vue

<template>
 <div>
 <van-cell-group>
  <van-field
   placeholder="名称/姓名"
   label="名称"
   v-model="data.name"
   :error-message="errorMsg.name"
  ></van-field>
  <van-field
   type="tel"
   placeholder="请输入手机号码"
   label="手机"
   v-model="data.mobile"
   :error-message="errorMsg.mobile"
   @click-icon="data.mobile = ''"
   icon="clear"
  ></van-field>
  <van-field
   center
   v-model="data.code"
   label="短信验证码"
   placeholder="请输入验证码"
   icon="clear"
   :error-message="errorMsg.code"
   @click-icon="data.code = ''"
  >
  <van-button
   slot="button"
   size="small"
   :disabled="countdown > 0"
   @click="sendMobileCode"
   type="primary">
   {{ countdown ? countdown + 's' : '发送'}}
  </van-button>
  </van-field>
 </van-cell-group>
 <div class="pad-all mar-top">
  <van-button
   block
   type="primary"
   @click="submit">
  立即注册
  </van-button>
  <van-button
   block
   class="mar-top"
   @click="reset">
  重置
  </van-button>
 </div>
 </div>
</template>
<script>
 import {Field, CellGroup, Cell, Button, Toast} from 'vant';
 import validator from './validator.js'

 export default {
 name: 'Demo',
 components: {
  [Field.name]: Field,
  [Button.name]: Button,
  [Cell.name]: Cell,
 },
 data() {
  return {
  countdown: 0,
  data: {
   name: '',
   mobile: '',
   code: '',
  },
  errorMsg: {
   name: '',
   mobile: '',
   code: '',
  },
  rules: {
   name: [
   {required: true, message: '请输入名称'}
   ],
   mobile: [
   {
    validator: (rule, value, callback) => {
    if (!value) {
     callback('请输入手机号码');
    } else if (/^[1][0-9]{10}$/.test(value)) {
     callback();
    } else {
     callback('请输入正确的手机号码');
    }
    }
   }
   ],
   code: [
   {required: true, message: '请输入验证码'}
   ]
  },
  }
 },
 methods: {
  sendMobileCode() {
  this.validate(errors => {
   if (!errors) {
   Toast('发送成功');
   this.countdown = 60;
   this.countdownSubtract();
   }
  }, 'mobile')
  },
  countdownSubtract() {
  if (this.countdown > 0) {
   setTimeout(() => {
   this.countdown -= 1;
   this.countdownSubtract()
   }, 1000)
  }
  },
  /**
  * 清除验证提示
  * @param attrs
  */
  resetField(attrs) {
  attrs = !attrs ? Object.keys(this.errorMsg) : ( Array.isArray(attrs) ? attrs : [attrs]);
  attrs.forEach(attr => {
   this.errorMsg[attr] = ''
  })
  },
  /**
  * 验证方法
  * @param callback
  * @param data
  */
  validate(callback, data) {
  this.validator.validate((errors, fields) => {
   this.resetField();
   if (errors) {
   fields.forEach(item => {
    this.errorMsg[item.field] = item.message
   })
   }
   callback && callback(errors, fields)
  }, data);
  },
  submit() {
  this.validate((errors, fields) => {

  })
  },
  reset() {
  this.data = {
   name: '',
   code: '',
   mobile: '',
  };
  this.validator.setData(this.data);
  this.resetField();
  },
 },
 created() {
  this.validator = validator(this.rules, this.data);
 },
 }
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript的IE和Firefox兼容性汇编
Jul 01 Javascript
Javascript中判断变量是数组还是对象(array还是object)
Aug 14 Javascript
js简单实现让文本框内容逐个字的显示出来
Oct 22 Javascript
Javascript浅谈之this
Dec 17 Javascript
浅析jQuery中调用ajax方法时在不同浏览器中遇到的问题
Jun 11 Javascript
jquery中的常用事件bind、hover、toggle等示例介绍
Jul 21 Javascript
Javascript中的几种URL编码方法比较
Jan 23 Javascript
Bootstrap分页插件之Bootstrap Paginator实例详解
Oct 15 Javascript
AngularJS路由Ui-router模块用法示例
May 29 Javascript
详解React开发必不可少的eslint配置
Feb 05 Javascript
element-ui 的el-button组件中添加自定义颜色和图标的实现方法
Oct 26 Javascript
VUE前后端学习tab写法实例
Aug 06 Javascript
使用react render props实现倒计时的示例代码
Dec 06 #Javascript
微信小程序冒泡事件及其阻止方法实例分析
Dec 06 #Javascript
谈谈React中的Render Props模式
Dec 06 #Javascript
详解Vue-axios 设置请求头问题
Dec 06 #Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
Dec 06 #jQuery
jQuery动态操作表单示例【基于table表格】
Dec 06 #jQuery
js防抖和节流的深入讲解
Dec 06 #Javascript
You might like
怎么样可以把 phpinfo()屏蔽掉?
2006/11/24 PHP
PHP CURL模拟GET及POST函数代码
2010/04/25 PHP
Yii全局函数用法示例
2017/01/22 PHP
PHP设计模式之装饰器(装饰者)模式(Decorator)入门与应用详解
2019/12/13 PHP
javascript XML数据显示为HTML一例
2008/12/23 Javascript
解决jquery的.animate()函数在IE6下的问题
2010/12/03 Javascript
JS获取月的最后一天与JS得到一个月份最大天数的实例代码
2013/12/16 Javascript
javascript实现按回车键切换焦点
2015/02/09 Javascript
Javascript之Math对象详解
2016/06/07 Javascript
js验证框架之RealyEasy验证详解
2016/06/08 Javascript
bootstrap select插件封装成Vue2.0组件
2017/04/17 Javascript
AngularJS入门教程二:在路由中传递参数的方法分析
2017/05/27 Javascript
vue中的event bus非父子组件通信解析
2017/10/27 Javascript
如何根据业务封装自己的功能组件
2019/04/19 Javascript
jQuery-Citys省市区三级菜单联动插件使用详解
2019/07/26 jQuery
python模拟鼠标拖动操作的方法
2015/03/11 Python
Python中的Classes和Metaclasses详解
2015/04/02 Python
深入解析Python中的urllib2模块
2015/11/13 Python
详解用Python处理HTML转义字符的5种方式
2017/12/27 Python
python并发编程之线程实例解析
2017/12/27 Python
python实战之实现excel读取、统计、写入的示例讲解
2018/05/02 Python
pandas DataFrame索引行列的实现
2019/06/04 Python
wxPython多个窗口的基本结构
2019/11/19 Python
python在一个范围内取随机数的简单实例
2020/08/16 Python
Python用SSH连接到网络设备
2021/02/18 Python
10分钟理解CSS3 Grid布局
2018/12/20 HTML / CSS
Bootstrap 学习分享
2012/11/12 HTML / CSS
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
澳大利亚制造的蜡烛和扩散器:Glasshouse Fragrances
2018/05/20 全球购物
攀岩、滑雪、徒步旅行装备:Black Diamond Equipment
2019/08/16 全球购物
医学专业毕业生个人的求职信
2013/12/04 职场文书
经贸日语专业个人求职信范文
2013/12/28 职场文书
审计主管岗位职责
2014/01/31 职场文书
2015年乡镇工会工作总结
2015/05/19 职场文书
你会写报告?产品体验报告到底该怎么写?
2019/08/14 职场文书
javascript中Set、Map、WeakSet、WeakMap区别
2022/12/24 Javascript