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 对象的创建与使用
Mar 09 Javascript
DOM 基本方法
Jul 18 Javascript
prototype 中文参数乱码解决方案
Nov 09 Javascript
jQuery动画效果animate和scrollTop结合使用实例
Apr 02 Javascript
Javascript基础之数组的使用
May 13 Javascript
JavaScript中的操作符类型转换示例总结
May 30 Javascript
单击按钮发送验证码,出现倒计时的简单实例
Mar 17 Javascript
原生JS实现隐藏显示图片 JS实现点击切换图片效果
Jan 27 Javascript
JavaScript html5 canvas实现图片上画超链接
Oct 20 Javascript
vue中使用mxgraph的方法实例代码详解
May 17 Javascript
JavaScript动态添加数据到表单并提交的几种方式
Jun 26 Javascript
在Vue中实现随hash改变响应菜单高亮
Mar 09 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新手上路(十)
2006/10/09 PHP
PHP安全配置详细说明
2011/09/26 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
2016/01/22 PHP
解决PHP使用CURL发送GET请求时传递参数的问题
2019/10/11 PHP
基于PHP的登录和注册的功能的实现
2020/08/06 PHP
PHP safe_mode开启对于PHP系统函数有什么影响
2020/11/10 PHP
TextArea 控件的最大长度问题(js json)
2009/12/16 Javascript
js getElementsByTagName的简写方式
2010/06/27 Javascript
提示$ is not defined错误分析及解决
2013/04/09 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
jQuery实现动画效果的简单实例
2014/01/27 Javascript
再分享70+免费的jquery 图片滑块效果插件和教程
2014/12/15 Javascript
JavaScript实现的encode64加密算法实例分析
2015/04/15 Javascript
深入理解jQuery 事件处理
2016/06/14 Javascript
深入浅析search 搜索框的写法
2016/08/02 Javascript
Actionscript与javascript交互实例程序(修改)
2016/09/22 Javascript
纯JS实现图片验证码功能并兼容IE6-8(推荐)
2017/04/19 Javascript
React BootStrap用户体验框架快速上手
2018/03/06 Javascript
vue+element-ui实现表格编辑的三种实现方式
2018/10/31 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
JavaScript享元模式原理与用法实例详解
2020/03/09 Javascript
[01:11:27]2018DOTA2亚洲邀请赛小组赛 A组加赛 Newbee vs Optic
2018/04/03 DOTA
Python单例模式实例详解
2017/03/01 Python
python的构建工具setup.py的方法使用示例
2017/10/23 Python
Python基于matplotlib实现绘制三维图形功能示例
2018/01/18 Python
python  Django中的apps.py的目的是什么
2018/10/15 Python
在cmd中查看python的安装路径方法
2019/07/03 Python
Pandas实现DataFrame按行求百分数(比例数)
2019/12/27 Python
pytorch中获取模型input/output shape实例
2019/12/30 Python
Python类成员继承重写的实现
2020/09/16 Python
美国第二大连锁书店:Books-A-Million
2017/12/28 全球购物
什么是Web Service?
2012/07/25 面试题
《走一步再走一步》教学反思
2014/02/15 职场文书
五年级小学生评语
2014/12/26 职场文书
2015年教师个人业务工作总结
2015/10/23 职场文书
Win11 vmware不兼容怎么办?Win11与VMware虚拟机不兼容的解决方法
2023/01/09 数码科技