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 相关文章推荐
ExtJS 2.0实用简明教程 之获得ExtJS
Apr 29 Javascript
JS获得选取checkbox整行数据的方法
Jan 28 Javascript
url传递的参数值中包含&amp;时,url自动截断问题的解决方法
Aug 02 Javascript
bootstrap-datetimepicker实现只显示到日期的方法
Nov 25 Javascript
Bootstrap php制作动态分页标签
Dec 23 Javascript
基于Vue2.0的分页组件
Mar 16 Javascript
Javascript中click与blur事件的顺序详析
Apr 25 Javascript
JS设计模式之单例模式(一)
Sep 29 Javascript
浅谈React组件之性能优化
Mar 02 Javascript
Vue+webpack+Element 兼容问题总结(小结)
Aug 16 Javascript
node koa2 ssr项目搭建的方法步骤
Dec 11 Javascript
Vue过滤器,生命周期函数和vue-resource简单介绍
Jan 12 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
php预定义常量
2006/12/25 PHP
隐性调用php程序的方法
2009/03/09 PHP
PHP开发框架laravel安装与配置教程
2015/03/13 PHP
4种PHP异步执行的常用方式
2015/12/24 PHP
php mongodb操作类 带几个简单的例子
2016/08/25 PHP
PHP调用Mailgun发送邮件的方法
2017/05/04 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 2异步获取节点)
2007/03/10 Javascript
JavaScript中json使用自己总结
2013/08/13 Javascript
节点的插入之append()和appendTo()的用法介绍
2014/01/13 Javascript
JavaScript中最简洁的编码html字符串的方法
2014/10/11 Javascript
JavaScript实现的双向跨域插件分享
2015/01/31 Javascript
JS模拟bootstrap下拉菜单效果实例
2016/06/17 Javascript
Ext JS动态加载JavaScript创建窗体的方法
2016/06/23 Javascript
jquery购物车结算功能实现方法
2020/10/29 Javascript
微信小程序地图导航功能实现完整源代码附效果图(推荐)
2019/04/28 Javascript
vue cli 3.0 搭建项目的图文教程
2019/05/17 Javascript
layui type2 通过url给iframe子页面传值的例子
2019/09/06 Javascript
vue指令v-html使用过滤器filters功能实例
2019/10/25 Javascript
js生成1到100的随机数最简单的实现方法
2020/02/07 Javascript
node.js 微信开发之定时获取access_token
2020/02/07 Javascript
使用JavaScript和MQTT开发物联网应用示例解析
2020/08/07 Javascript
ant design 日期格式化的实现
2020/10/27 Javascript
Vue ​v-model相关知识总结
2021/01/28 Vue.js
[54:08]LGD女子刀塔学院 DOTA2炼金术士教学
2014/01/09 DOTA
详解Django中的过滤器
2015/07/16 Python
Django 返回json数据的实现示例
2020/03/05 Python
CSS3 渐变(Gradients)之CSS3 径向渐变
2016/07/08 HTML / CSS
英国女士和男士时尚服装网上购物:Top Labels Online
2018/03/25 全球购物
ASICS印度官方网站:日本专业运动品牌
2020/06/20 全球购物
Static Nested Class 和 Inner Class的不同
2013/11/28 面试题
总会计师岗位职责
2014/02/19 职场文书
预备党员自我批评思想汇报
2014/10/10 职场文书
郭明义电影观后感
2015/06/08 职场文书
催款函范文
2015/06/24 职场文书
2019学生会干事辞职信
2019/06/27 职场文书
关于nginx 实现jira反向代理的问题
2021/09/25 Servers