ElementUI多個子組件表單的校驗(yàn)管理實(shí)現(xiàn)
背景
公司項(xiàng)目中所用到的前端框架是Vue.js + ElementUI,因?yàn)轫?xiàng)目的業(yè)務(wù)場景中有很多的大表單,但是ElementUI的表單寫法對于表單的拆分和校驗(yàn)其實(shí)并不是很友好。最初的項(xiàng)目為了方便,常常把多個表單寫在一個.vue組件中,這導(dǎo)致單文件的代碼量巨大,邏輯十分復(fù)雜。目前為了維護(hù)方便,表單的拆分就變得十分重要。
現(xiàn)在做了以下的Demo說明我們的業(yè)務(wù)場景,父組件是App.vue,該組件中包含了PersonForm.vue和AdsForm.vue這兩個子組件(在實(shí)際的業(yè)務(wù)場景中,可能多達(dá)10+表單)。【提交】按鈕在父組件App.vue中,當(dāng)點(diǎn)擊【提交】按鈕后,應(yīng)該分別校驗(yàn)各個子組件,如果每個子組件都校驗(yàn)成功后再進(jìn)行提交。
Demo
PersonForm.vue文件
下面的代碼是PersonForm.vue組件,該表單包括姓名、年齡、性別。我們使用了PersonForm這個類去實(shí)例化組件中的personForm的值。在PersonForm中有個static方法getRule去獲取校驗(yàn)方法去獲取校驗(yàn)對象,該校驗(yàn)對象是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這個類去實(shí)例化組件中的adsForm的值。在AdsForm中有個static方法getRule去獲取校驗(yàn)方法去獲取校驗(yàn)對象。
<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中我們導(dǎo)入了validator.js中的校驗(yàn)方法,這些校驗(yàn)方法中封裝了對表單屬性值的校驗(yàn)規(guī)則。該文件中的方法在實(shí)際項(xiàng)目中,應(yīng)該使用策略模式再封裝一下。Demo中只有4個方法,就沒有再封裝來干擾讀者理解代碼。
// 驗(yàn)證名字 var validateName = (rule, value, callback) => { if(!value) { callback(new Error('名字不能為空')); } else if(/[a-zA-Z]/.test(value)) { callback(new Error('請?zhí)顚懼形拿郑?)); } else { callback(); } }; // 驗(yàn)證年齡 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('年齡為數(shù)值類型')); } else if(!(toNumberVal > 0 && toNumberVal <= 120)) { callback(new Error('年齡范圍應(yīng)該大于一歲且小于等于120歲')); } else { callback(); } } // 驗(yàn)證性別 var validateSex = (rule, value, callback) => { if (value === null) { callback(new Error('性別不允許為空')); } { callback(); } } // 驗(yàn)證不為空 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是父組件,當(dāng)點(diǎn)擊【提交】按鈕時,應(yīng)該調(diào)用其ElmentUI的this.$refs[formName].validate方法去驗(yàn)證各個子組件中的表單。但是需要注意的是,該方法是一個異步方法。
所以這里封裝了一個getFormPromise去生成Promise對象,并使用Promise.all去并行調(diào)用返回最終的校驗(yàn)結(jié)果數(shù)組。
<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去校驗(yàn)結(jié)果 Promise.all([personForm, adsForm].map(this.getFormPromise)).then(res => { const validateResult = res.every(item => !!item); if (validateResult) { console.log('兩個表單都校驗(yàn)通過'); } else { console.log('兩個表單未校驗(yàn)通過'); } }) }, 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>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue中使用JsonView來展示Json樹的實(shí)例代碼
這篇文章主要介紹了Vue之使用JsonView來展示Json樹的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11Vue中使用js制作進(jìn)度條式數(shù)據(jù)對比動畫
這篇文章主要為大家詳細(xì)介紹了Vue中使用js制作進(jìn)度條式數(shù)據(jù)對比動畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03在nginx上部署vue項(xiàng)目(history模式)的方法
vue-router 默認(rèn)是hash模式,使用url的hash來模擬一個完整的url,當(dāng)url改變的時候,頁面不會重新加載。這篇文章主要介紹了在nginx上部署vue項(xiàng)目(history模式),需要的朋友可以參考下2017-12-12vue實(shí)現(xiàn)文字轉(zhuǎn)語音功能詳解
這篇文章主要介紹了vue實(shí)現(xiàn)文字轉(zhuǎn)語音功能詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09vue本地打開build后生成的dist文件夾index.html問題
這篇文章主要介紹了vue本地打開build后生成的dist文件夾index.html問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友參考下吧2019-09-09解決vue-cli項(xiàng)目開發(fā)運(yùn)行時內(nèi)存暴漲卡死電腦問題
最近開發(fā)一個vue項(xiàng)目時遇到電腦卡死問題,突然間系統(tǒng)就非??ǎ缓罂ㄖㄖ退罊C(jī)了,鼠標(biāo)也動不了了,只能冷啟動。這篇文章主要介紹了vue-cli項(xiàng)目開發(fā)運(yùn)行時內(nèi)存暴漲卡死電腦問題,需要的朋友可以參考下2019-10-10vue ssr 實(shí)現(xiàn)方式(學(xué)習(xí)筆記)
這篇文章主要介紹了vue ssr 實(shí)現(xiàn)方式(學(xué)習(xí)筆記),本文不涉及到源碼解析,主要講解如何實(shí)現(xiàn) vue 的服務(wù)端渲染,比較適合 vue-ssr 小白閱讀,感興趣的小伙伴們可以參考一下2019-01-01vue 在methods中調(diào)用mounted的實(shí)現(xiàn)操作
這篇文章主要介紹了vue 在methods中調(diào)用mounted的實(shí)現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08