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 相关文章推荐
Jquery中LigerUi的弹出编辑框(实现方法)
Jul 09 Javascript
javascript中定义私有方法说明(private method)
Jan 27 Javascript
JS 弹出层 定位至屏幕居中示例
May 21 Javascript
Node.js + Redis Sorted Set实现任务队列
Sep 19 Javascript
Javascript 实现全屏滚动实例代码
Dec 31 Javascript
浅谈angularjs依赖服务注入写法的注意点
Apr 24 Javascript
jQuery输入框密码的显示隐藏【代码分享】
Apr 29 jQuery
Angular中ng-repeat与ul li的多层嵌套重复问题
Jul 24 Javascript
ES6中Array.includes()函数的用法
Sep 20 Javascript
javascript操作元素的常见方法小结
Nov 13 Javascript
JavaScript实现留言板案例
Mar 17 Javascript
React如何使用axios请求数据并把数据渲染到组件
Aug 05 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变量的定义、可变变量、变量引用、销毁方法
2013/12/20 PHP
PHP编程中的常见漏洞和代码实例
2014/08/06 PHP
PHP文件操作详解
2016/12/30 PHP
php中的异常和错误浅析
2017/05/03 PHP
ThinkPHP整合datatables实现服务端分页的示例代码
2018/02/10 PHP
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
2013/02/05 Javascript
js控制web打印(局部打印)方法整理
2013/05/29 Javascript
node.js中的fs.fchown方法使用说明
2014/12/16 Javascript
Node.js开源应用框架HapiJS介绍
2015/01/14 Javascript
jquery实现键盘左右翻页特效
2015/04/30 Javascript
js控制文本框禁止输入特殊字符详解
2017/04/07 Javascript
基于JavaScript实现活动倒计时效果
2017/04/20 Javascript
如何在 Vue.js 中使用第三方js库
2017/04/25 Javascript
SpringMVC+bootstrap table实例详解
2017/06/02 Javascript
vue实现一个移动端屏蔽滑动的遮罩层实例
2017/06/08 Javascript
vue.js input框之间赋值方法
2018/08/24 Javascript
微信小程序 轮播图实现原理及优化详解
2019/09/29 Javascript
[02:07]DOTA2新英雄展现中国元素,完美“圣典”亮相央视
2016/12/19 DOTA
wxPython窗口的继承机制实例分析
2014/09/28 Python
Anaconda下安装mysql-python的包实例
2018/06/11 Python
python+mysql实现学生信息查询系统
2019/02/21 Python
Python函数定义及传参方式详解(4种)
2019/03/18 Python
Python 日期区间处理 (本周本月上周上月...)
2019/08/08 Python
pytorch 输出中间层特征的实例
2019/08/17 Python
在tensorflow中设置使用某一块GPU、多GPU、CPU的操作
2020/02/07 Python
屏蔽Django admin界面添加按钮的操作
2020/03/11 Python
使用Python和百度语音识别生成视频字幕的实现
2020/04/09 Python
Python 多线程共享变量的实现示例
2020/04/17 Python
中软国际Java程序员机试题
2012/08/19 面试题
生物技术毕业生自荐信
2013/10/23 职场文书
路政管理专业个人自荐信范文
2013/11/30 职场文书
美食节目策划方案
2014/05/31 职场文书
党员学习中共十八大报告思想汇报
2014/09/15 职场文书
实习报告范文之电话客服岗位
2019/07/26 职场文书
php实现自动生成验证码的实例讲解
2021/11/17 PHP
Windows server 2012 R2 安装IIS服务器
2022/04/29 Servers