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 解析xml文件
Aug 09 Javascript
Js sort排序使用方法
Oct 17 Javascript
javaScript 利用闭包模拟对象的私有属性
Dec 29 Javascript
AngularJS的内置过滤器详解
May 14 Javascript
移动端日期插件Mobiscroll.js使用详解
Dec 19 Javascript
基于Javascript实现的不重复ID的生成器
Dec 25 Javascript
js中document.referrer实现移动端返回上一页
Feb 22 Javascript
Three.js基础学习之场景对象
Sep 27 Javascript
原生JS实现简单的倒计时功能示例
Aug 30 Javascript
layui 实现表格某一列显示图标
Sep 19 Javascript
vue实现随机验证码功能(完整代码)
Dec 10 Javascript
vue子组件改变父组件传递的prop值通过sync实现数据双向绑定(DEMO)
Feb 01 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
BBS(php &amp; mysql)完整版(四)
2006/10/09 PHP
IIS php环境配置PHP5 MySQL5 ZendOptimizer phpmyadmin安装与配置
2008/11/18 PHP
在PHP中使用反射技术的架构插件使用说明
2010/05/18 PHP
PHP取进制余数函数代码
2012/01/19 PHP
PHP中使用FFMPEG获取视频缩略图和视频总时长实例
2014/05/04 PHP
jQuery 性能优化指南 (1)
2009/05/21 Javascript
jQuery ctrl+Enter shift+Enter实现代码
2010/02/07 Javascript
javaScript checkbox 全选/反选及批量删除
2010/04/28 Javascript
jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)
2012/03/21 Javascript
浅谈JavaScript中的Math.atan()方法的使用
2015/06/14 Javascript
AngularJS 使用 UI Router 实现表单向导
2016/01/29 Javascript
jQuery simplePage+AJAX plus分页插件用法实例
2016/02/17 Javascript
手机浏览器 后退按钮强制刷新页面方法总结
2016/10/09 Javascript
JS时间控制实现动态效果的实例讲解
2017/07/31 Javascript
自己动手封装一个React Native多级联动
2018/09/19 Javascript
electron实现静默打印的示例代码
2019/08/12 Javascript
微信小程序如何播放腾讯视频的实现
2019/09/20 Javascript
微信小程序 textarea 层级过高问题简单解决方案
2019/10/14 Javascript
JavaScript实现电灯开关小案例
2020/03/30 Javascript
在vue-cli3中使用axios获取本地json操作
2020/07/30 Javascript
如何在面试中手写出javascript节流和防抖函数
2020/10/22 Javascript
Python Tkinter基础控件用法
2014/09/03 Python
解决python3中解压zip文件是文件名乱码的问题
2018/03/22 Python
python实现从文件中读取数据并绘制成 x y 轴图形的方法
2018/10/14 Python
Python传递参数的多种方式(小结)
2019/09/18 Python
Python sys模块常用方法解析
2020/02/20 Python
python利用paramiko实现交换机巡检的示例
2020/09/22 Python
基于css3仿造window7的开始菜单
2010/06/17 HTML / CSS
中学自我评价
2014/01/31 职场文书
社会体育专业大学生职业生涯规划书
2014/09/17 职场文书
民主生活会对照检查材料范文
2014/10/01 职场文书
2014年煤矿工作总结
2014/11/24 职场文书
交通事故被告代理词
2015/05/23 职场文书
pandas中DataFrame重置索引的几种方法
2021/05/24 Python
pandas中DataFrame检测重复值的实现
2021/05/26 Python
详解Anyscript开发指南绕过typescript类型检查
2022/09/23 Javascript