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 相关文章推荐
JavaScript 获得选中文本内容的方法
Feb 15 Javascript
Javascript页面添加到收藏夹的简单方法
Aug 07 Javascript
JS 打印界面的CSS居中代码适用所有浏览器
Mar 19 Javascript
js分页工具实例
Jan 28 Javascript
jQuery选择id属性带有点符号元素的方法
Mar 17 Javascript
JavaScript控制按钮可用或不可用的方法
Apr 03 Javascript
JavaScript中Cookies的相关使用教程
Jun 04 Javascript
JavaScript清空数组元素的两种方法简单比较
Jul 10 Javascript
.net MVC+Bootstrap下使用localResizeIMG上传图片
Apr 21 Javascript
详解Vue源码学习之callHook钩子函数
Jul 25 Javascript
JavaScript arguments.callee作用及替换方案详解
Sep 02 Javascript
vue3.0搭配.net core实现文件上传组件
Oct 29 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 字符串正则替换函数preg_replace使用说明
2011/07/15 PHP
UCenter 批量添加用户的php代码
2012/07/17 PHP
PHP中使用sleep函数实现定时任务实例分享
2014/08/21 PHP
php中rename函数用法分析
2014/11/15 PHP
深入理解JavaScript 闭包究竟是什么
2013/04/12 Javascript
jquery实现文本框数量加减功能的例子分享
2014/05/10 Javascript
用Angular实时获取本地Localstorage数据,实现一个模拟后台数据登入的效果
2016/11/09 Javascript
如何提高Dom访问速度
2017/01/05 Javascript
Vue.js render方法使用详解
2017/04/05 Javascript
js实现倒计时关键代码
2017/05/05 Javascript
微信小程序实现流程进度的图样式功能
2018/01/16 Javascript
js动态引入的四种方法
2018/05/05 Javascript
CryptoJS中AES实现前后端通用加解密技术
2018/12/18 Javascript
JavaScript代码调试方法实例小结
2019/01/05 Javascript
vue组件化中slot的基本使用方法
2019/05/01 Javascript
[50:15]VP vs Mineski 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
python 删除字符串中连续多个空格并保留一个的方法
2018/12/22 Python
Python 实现输入任意多个数,并计算其平均值的例子
2019/07/16 Python
pytorch 自定义卷积核进行卷积操作方式
2019/12/30 Python
Python转换字典成为对象,可以用&quot;.&quot;方式访问对象属性实例
2020/05/11 Python
Python3爬虫里关于Splash负载均衡配置详解
2020/07/10 Python
Python logging模块原理解析及应用
2020/08/13 Python
如何通过python计算圆周率PI
2020/11/11 Python
Python使用Pygame绘制时钟
2020/11/29 Python
python爬虫线程池案例详解(梨视频短视频爬取)
2021/02/20 Python
HTML 5 input placeholder 属性如何完美兼任ie
2014/05/12 HTML / CSS
Under Armour安德玛英国官网:美国高端运动科技品牌
2018/09/17 全球购物
Fnac西班牙官网:法国文化和电子产品零售商
2021/03/14 全球购物
幼儿园教学随笔感言
2014/02/23 职场文书
《他得的红圈圈最多》教学反思
2014/04/24 职场文书
希特勒的演讲稿
2014/05/23 职场文书
群众路线对照检查剖析材料
2014/10/09 职场文书
2014年体育部工作总结
2014/11/13 职场文书
小学一年级班主任工作经验交流材料
2015/11/02 职场文书
教师听课学习心得体会
2016/01/15 职场文书
一次SQL如何查重及去重的实战记录
2022/03/13 MySQL