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 相关文章推荐
将函数的实际参数转换成数组的方法
Jan 25 Javascript
js substring从右边获取指定长度字符串(示例代码)
Dec 23 Javascript
Get中文乱码IE浏览器Get中文乱码解决方案
Dec 26 Javascript
事件委托与阻止冒泡阻止其父元素事件触发
Sep 02 Javascript
微信小程序 火车票查询实例讲解
Oct 17 Javascript
详解微信小程序开发之下拉刷新 上拉加载
Nov 24 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
Dec 14 Javascript
Vue组件之高德地图地址选择功能的实例代码
Jun 21 Javascript
微信小程序利用button控制条件标签的变量问题
Mar 15 Javascript
Angular利用HTTP POST下载流文件的步骤记录
Jul 26 Javascript
在vue中使用回调函数,this调用无效的解决
Aug 11 Javascript
Vue.extend 登录注册模态框的实现
Dec 29 Vue.js
使用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
dedecms采集中可以过滤多行代码的正则表达式
2007/03/17 PHP
php基础教程
2015/08/26 PHP
YII框架常用技巧总结
2019/04/27 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
2019/11/24 PHP
JavaScript 事件对象的实现
2009/07/13 Javascript
JS面向对象编程 for Cookie
2010/09/19 Javascript
浅谈Javascript实现继承的方法
2015/07/06 Javascript
jquery选择器简述
2015/08/31 Javascript
Vue.JS入门教程之自定义指令
2016/12/08 Javascript
ionic开发中点击input时键盘自动弹出
2016/12/23 Javascript
js实现固定宽高滑动轮播图效果
2017/01/13 Javascript
jQuery ajax调用webservice注意事项
2017/10/08 jQuery
在vscode里使用.vue代码模板的方法
2018/04/28 Javascript
浅谈React 服务器端渲染的使用
2018/05/08 Javascript
Vue实现一个图片懒加载插件
2019/03/11 Javascript
angular多语言配置详解
2019/05/16 Javascript
JS实现移动端在线签协议功能
2019/08/22 Javascript
Python创建系统目录的方法
2015/03/11 Python
日常整理python执行系统命令的常见方法(全)
2015/10/22 Python
Python实现的FTP通信客户端与服务器端功能示例
2018/03/28 Python
用python处理图片实现图像中的像素访问
2018/05/04 Python
Python根据欧拉角求旋转矩阵的实例
2019/01/28 Python
python 实现dict转json并保存文件
2019/12/05 Python
Python中实现输入超时及如何通过变量获取变量名
2020/01/18 Python
python encrypt 实现AES加密的实例详解
2020/02/20 Python
Python浮点型(float)运算结果不正确的解决方案
2020/09/22 Python
html5自定义video标签的海报与播放按钮功能
2019/12/04 HTML / CSS
使用layui实现左侧菜单栏及动态操作tab项的方法
2020/11/10 HTML / CSS
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
电气专业应届生求职信
2013/11/01 职场文书
会计工作心得体会
2014/01/13 职场文书
高三家长寄语
2014/04/03 职场文书
中国梦演讲稿范文
2014/08/28 职场文书
群众路线剖析材料(四风)
2014/11/05 职场文书
小学数学教学反思范文
2016/02/16 职场文书
JavaScript 中for/of,for/in 的详细介绍
2021/11/17 Javascript