ElementUI多个子组件表单的校验管理实现


Posted in Javascript onNovember 07, 2019

背景

公司项目中所用到的前端框架是Vue.js + ElementUI,因为项目的业务场景中有很多的大表单,但是ElementUI的表单写法对于表单的拆分和校验其实并不是很友好。最初的项目为了方便,常常把多个表单写在一个.vue组件中,这导致单文件的代码量巨大,逻辑十分复杂。目前为了维护方便,表单的拆分就变得十分重要。

现在做了以下的Demo说明我们的业务场景,父组件是App.vue,该组件中包含了PersonForm.vue和AdsForm.vue这两个子组件(在实际的业务场景中,可能多达10+表单)。【提交】按钮在父组件App.vue中,当点击【提交】按钮后,应该分别校验各个子组件,如果每个子组件都校验成功后再进行提交。

ElementUI多个子组件表单的校验管理实现

Demo

PersonForm.vue文件

下面的代码是PersonForm.vue组件,该表单包括姓名、年龄、性别。我们使用了PersonForm这个类去实例化组件中的personForm的值。在PersonForm中有个static方法getRule去获取校验方法去获取校验对象,该校验对象是ElementUI要求的写法,会在<el-form>的rules中定义。

<template>
 <div class="person-form">
  <h2>PersonForm.vue</h2>
  <el-form :model="personForm" ref="personForm" :rules="personFormRules">
   <!-- 姓名 -->
   <el-form-item label="姓名" prop="name">
    <el-input v-model="personForm.name"></el-input>
   </el-form-item>
   <!-- 年龄 -->
   <el-form-item label="年龄" prop="age">
    <el-input v-model="personForm.age"></el-input>
   </el-form-item>
   <!-- 性别 -->
   <el-form-item label="性别" prop="sex">
    <el-radio-group v-model="personForm.sex">
     <el-radio label="0">男</el-radio>
     <el-radio label="1">女</el-radio>
    </el-radio-group>
   </el-form-item>
  </el-form>
 </div>
</template>

<script>
import {validateName, validateAge, validateSex } from '@/lib/validator.js';

// PersonForm的类
class PersonForm {
 constructor() {
  this.name = '';
  this.age = null;
  this.sex = null;
 }

 static getRule() {
  return {
   name: [{ validator: validateName, trigger: 'blur' }],
   age: [{ validator: validateAge, trigger: 'blur' }],
   sex: [{validator: validateSex, trigger: 'blur'}],
  }
 }
}

export default {
 data() {
  return {
   personForm: new PersonForm(),
   personFormRules: PersonForm.getRule()
  }
 }
}
</script>

<style>
 .person-form {
  width: 400px;
  height: 350px;
  padding: 20px;
  border: 1px solid #ccc;
 }
</style>

AdsForm.vue文件

下面的代码是AdsForm.vue组件,该表单包括广告名和广告位置。我们使用了AdsForm这个类去实例化组件中的adsForm的值。在AdsForm中有个static方法getRule去获取校验方法去获取校验对象。

<template>
 <div class="ads-form">
   <h2>AdsForm.vue</h2>
   <el-form :model="adsForm" ref="adsForm" :rules="adsFormRules">
   <!-- 广告名 -->
   <el-form-item label="广告名" prop="name">
    <el-input v-model="adsForm.name"></el-input>
   </el-form-item>
   <!-- 广告位置 -->
   <el-form-item label="广告位置" prop="position">
    <el-select v-model="adsForm.position">
     <el-option value="1" label="左上"></el-option>
     <el-option value="2" label="右上"></el-option>
     <el-option value="3" label="左下"></el-option>
     <el-option value="4" label="右下"></el-option>
    </el-select>
   </el-form-item>
  </el-form>
 </div>
</template>

<script>
import { notEmpty, validateName } from '@/lib/validator.js';

class AdsForm {
 constructor() {
  this.name = '';
  this.position = null;
 }

 static getRule() {
  return {
   name: [{ validator: validateName, trigger: 'blur' }],
   position: [{ validator: notEmpty, trigger: 'blur' }],
  }
 }
}

export default {
 data() {
  return {
   adsForm: new AdsForm(),
   adsFormRules: AdsForm.getRule()
  }
 }
}
</script>

<style>
 .ads-form {
  width: 400px;
  height: 350px;
  padding: 20px;
  border: 1px solid #ccc;
  margin-left: 30px;
 }
</style>

validator.js文件

在PersonForm.vue 和 AdsForm.vue中我们导入了validator.js中的校验方法,这些校验方法中封装了对表单属性值的校验规则。该文件中的方法在实际项目中,应该使用策略模式再封装一下。Demo中只有4个方法,就没有再封装来干扰读者理解代码。

// 验证名字
var validateName = (rule, value, callback) => {
 if(!value) {
  callback(new Error('名字不能为空'));
 } else if(/[a-zA-Z]/.test(value)) {
  callback(new Error('请填写中文名字!'));
 } else {
  callback();
 }
};

// 验证年龄
var validateAge = (rule, value, callback) => {
 const toNumberVal = Number(value);
 if ((typeof value === 'string' && value === '') || (value === null)) {
  callback(new Error('年龄不允许为空'));
 } else if (isNaN(toNumberVal)) {
  callback(new Error('年龄为数值类型'));
 } else if(!(toNumberVal > 0 && toNumberVal <= 120)) {
  callback(new Error('年龄范围应该大于一岁且小于等于120岁'));
 } else {
  callback();
 }
}

// 验证性别
var validateSex = (rule, value, callback) => {
 if (value === null) {
  callback(new Error('性别不允许为空'));
 } {
  callback();
 }
}

// 验证不为空
var notEmpty = (rule, value, callback) => {
 if (value === '' || value === null || value === undefined) {
  callback(new Error('不允许为空'));
 } else {
  callback();
 }
}

export { 
  validateName, 
  validateAge, 
  validateSex,
  notEmpty,
}

App.vue

App.vue是父组件,当点击【提交】按钮时,应该调用其ElmentUI的this.$refs[formName].validate方法去验证各个子组件中的表单。但是需要注意的是,该方法是一个异步方法。

所以这里封装了一个getFormPromise去生成Promise对象,并使用Promise.all去并行调用返回最终的校验结果数组。

<template>
 <div class="app">
  <h1>App.vue</h1>

  <div class="forms-container">
   <!-- PersonForm.vue -->
   <person-form ref="personFormComp"/>
   <!-- AdsForm.vue -->
   <ads-form ref="adsFormComp"/>
  </div>

  <el-button 
   class="submit-btn" 
   @click="submitForm"
   type="primary">
   提交
  </el-button>
 </div>
</template>


<script>
import PersonForm from '@/components/PersonForm';
import AdsForm from '@/components/AdsForm.vue';

export default {
 components: {
  'person-form': PersonForm,
  'ads-form': AdsForm,
 },
 methods: {
  submitForm() {
   // 获取到组件中的form
   const personForm = this.$refs.personFormComp.$refs.personForm;
   const adsForm = this.$refs.adsFormComp.$refs.adsForm;
   // 使用Promise.all去校验结果
   Promise.all([personForm, adsForm].map(this.getFormPromise)).then(res => {
    const validateResult = res.every(item => !!item);
    if (validateResult) {
     console.log('两个表单都校验通过');
    } else {
     console.log('两个表单未校验通过');
    }
   })
  },
  getFormPromise(form) {
   return new Promise(resolve => {
    form.validate(res => {
     resolve(res);
    })
   })
  }
 }
}
</script>

<style>
.app {
 border: 1px solid #ccc;
 padding: 20px;
 width: 900px;
}
.app .submit-btn {
 margin-top: 40px;
}
.forms-container {
 display: flex;
}
</style>

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

Javascript 相关文章推荐
Prototype使用指南之enumerable.js
Jan 10 Javascript
用JavaScript将从数据库中读取出来的日期型格式化为想要的类型。
Aug 15 Javascript
js改变img标签的src属性在IE下没反应的解决方法
Jul 23 Javascript
JS动态修改iframe高度和宽度的方法
Apr 01 Javascript
使用Node.js配合Nginx实现高负载网络
Jun 28 Javascript
总结JavaScript三种数据存储方式之间的区别
May 03 Javascript
AngularJs directive详解及示例代码
Sep 01 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
Feb 16 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
May 01 jQuery
微信小程序自定义组件实现tabs选项卡功能
Jul 14 Javascript
解决Layui选择全部,换页checkbox复选框重新勾选的问题方法
Aug 14 Javascript
VUE 自定义组件模板的方法详解
Aug 30 Javascript
构建Vue大型应用的10个最佳实践(小结)
Nov 07 #Javascript
Node配合WebSocket做多文件下载以及进度回传
Nov 07 #Javascript
vue 实现单选框设置默认选中值
Nov 07 #Javascript
js使用文档就绪函数动态改变页面内容示例【innerHTML、innerText】
Nov 07 #Javascript
vue获取data数据改变前后的值方法
Nov 07 #Javascript
使用JS监听键盘按下事件(keydown event)
Nov 07 #Javascript
vue.js循环radio的实例
Nov 07 #Javascript
You might like
可以在线执行PHP代码包装修正版
2008/03/15 PHP
php简单实现批量上传图片的方法
2016/05/09 PHP
php 实现一个字符串加密解密的函数实例代码
2016/11/01 PHP
PHP带节点操作的无限分类实现方法详解
2016/11/09 PHP
php中替换字符串函数strtr()和str_repalce()的用法与区别
2016/11/25 PHP
PHP crypt()函数的用法讲解
2019/02/15 PHP
基于laravel Request的所有方法详解
2019/09/29 PHP
javascript:以前写的xmlhttp池,代码
2008/05/18 Javascript
关于jQuery中.attr()和.prop()的问题探讨
2013/09/06 Javascript
jqGrid日期格式的判断示例代码(开始日期与结束日期)
2013/11/08 Javascript
jQuery()方法的第二个参数详解
2015/04/29 Javascript
JS面向对象编程详解
2016/03/06 Javascript
vue proxyTable 接口跨域请求调试的示例
2017/09/12 Javascript
JS基于正则表达式实现的密码强度验证功能示例
2017/09/21 Javascript
通过实例解析js简易模块加载器
2019/06/17 Javascript
使用Vue调取接口,并渲染数据的示例代码
2019/10/28 Javascript
用jQuery实现抽奖程序
2020/04/12 jQuery
[52:52]完美世界DOTA2联赛PWL S3 LBZS vs access 第一场 12.10
2020/12/13 DOTA
在Python的web框架中编写创建日志的程序的教程
2015/04/30 Python
Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程
2016/06/14 Python
Python中GeoJson和bokeh-1的使用讲解
2019/01/03 Python
python3 字符串/列表/元组(str/list/tuple)相互转换方法及join()函数的使用
2019/04/03 Python
Python数据结构与算法(几种排序)小结
2019/06/22 Python
html5/css3响应式页面开发总结
2018/10/16 HTML / CSS
英国评分最高的女性剃须刀订阅盒:FFS Beauty
2018/01/25 全球购物
英国派对礼服和连衣裙购物网站:TFNC London
2018/07/07 全球购物
教学实习自我评价
2014/01/28 职场文书
校长先进事迹材料
2014/02/01 职场文书
医药类个人求职的自我评价
2014/02/12 职场文书
骨干教师培训方案
2014/05/06 职场文书
小学语文业务学习材料
2014/06/02 职场文书
干部作风建设年活动剖析材料
2014/10/23 职场文书
六一儿童节主持开场白
2015/05/28 职场文书
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
在项目中使用redis做缓存的一些思路
2021/09/14 Redis
MySql分区类型及创建分区的方法
2022/04/13 MySQL