vue開發中後臺系統復雜表單優化技巧
引言
在中後臺系統的日常開發中,表單必不可少,當表單內容比較多,例如有上百個字段(這一點都不誇張,血淋淋的現實)時,代碼往往也變得復雜且難以維護,加上各種動態聯動的表單校驗,無疑讓我們的頁面開發過程雪上加霜,本文將結合自己平時的開發習慣,分享一下在大表單開發中如何處理復雜的表單校驗,以及如何對表單進行拆分,減少單個文件堆積過多的代碼內容。
表單校驗
<template> <el-form ref="ruleForm" :rules="rules" :model="form" inline > <el-form-item label="企業性質" prop="natureEnterprise"> <el-select v-model="form.natureEnterprise"> <el-option label="國企" :value="1" /> <el-option label="事業單位" :value="2" /> <el-option label="個體戶" :value="3" /> </el-select> </el-form-item> <el-form-item label="業務類型" prop="type"> <el-select v-model="form.type"> <el-option label="護膚" :value="1" /> <el-option label="食品" :value="2" /> </el-select> </el-form-item> <el-form-item label="企業名稱" prop="name"> <el-input v-model="form.name" placeholder="請輸入"></el-input> </el-form-item> <el-form-item label="社會統一信用代碼" prop="creditCode"> <el-input v-model="form.creditCode" placeholder="請輸入"></el-input> </el-form-item> <el-form-item label="註冊地址" prop="address"> <el-input v-model="form.address" placeholder="請輸入"></el-input> </el-form-item> </el-form> </template> <script> export default { data() { return { form: { natureEnterprise: null, type: null, address: '', name: '', creditCode: '' }, rules: { natureEnterprise: [ { required: true, message: '企業性質不能為空', trigger: 'change' } ], type: [ { required: true, message: '業務類型不能為空', trigger: 'change' } ], address: [ { required: true, message: '註冊地址不能為空', trigger: 'change' } ], name: [ { required: true, message: '企業名稱不能為空', trigger: 'change' } ], creditCode: [ { required: true, message: '社會統一信用代碼不能為空', trigger: 'change' } ] } } } } </script>
以上表單為例,要求默認全部必填,如果企業性質為個體戶,則註冊地址和社會統一信用代碼為非必填,讓我們增加以下代碼來實現這個需求:
watch: { 'form.natureEnterprise': { hanlder(val) { this.rules.creditCode[0].required = val !== 3 this.rules.address[0].required = val !== 3 } } }
如果此時新增一個校驗,假設要求業務類型為護膚時,企業名稱非必填,那我們需要像上面監聽業務類型的值然後做相應的判斷,隨著表單內容的增多,我們的watch會越來越多,同時rules也會散落在不同的地方,這必然會為後續的代碼維護帶來困難,接手的人也必須小心翼翼的在上面做修改。
使用computed進行表單校驗優化
將rules作為計算屬性裡的值統一處理,而不是放在data裡,避免需要頻繁去操作data裡的rules,也避免rules的項散落在頁面各處。
computed: { rules({ form }) { // 是否個體戶 const isSelfEmploy = form.natureEnterprise === 3 return { natureEnterprise: [ { required: true, message: '企業性質不能為空', trigger: 'change' } ], type: [ { required: true, message: '業務類型不能為空', trigger: 'change' } ], name: [ { required: true, message: '企業名稱不能為空', trigger: 'change' } ], address: [ { required: !isSelfEmploy, message: '註冊地址不能為空', trigger: 'change' } ], creditCode: [ { required: !isSelfEmploy, message: '社會統一信用代碼不能為空', trigger: 'change' } ] } } }
改用computed後,會有一個問題:頁面初始加載或computed裡使用的相關值改變時會立即觸發檢驗。看起來體驗不是很好,el-form
有一個validate-on-rule-change
屬性,表示會在rules
屬性改變後立即觸發一次驗證,默認為true,將其設置為false即可
<el-form :validate-on-rule-change="false" ></el-form>
表單拆分
當表單內容變得龐大時,將其塞在一個文件裡進行開發時無疑會變得很臃腫。這時候我們可以將其拆分成一個一個的組件,每個組件裡獨立負責自己的表單內容以及校驗,最後提交時由父組件統一收集每個子組件的數據進行提交,這樣避免瞭所有內容都放在一個文件裡變得大而雜,同時也有利於團隊多人進行開發,減少沖突。
// 父組件:main-form.vue <template> <!-- 子組件-基礎信息表單 --> <base-form ref="baseFormRef" /> <!-- 子組件-合作信息表單 --> <coop-form ref="coopFormRef" /> <el-button type="primary" @click="handleSave">保存</el-button> </template> <script> import BaseForm from './base-form' import CoopForm from './coop-form' export default { components: { BaseForm, CoopForm }, methods: { async handleSave() { // 調用子組件提供的方法,獲取表單數據 const baseFormData = await this.$refs['baseFormRef'].validate() const coopFormData = await this.$refs['coopFormRef'].validate() if (baseFormData && coopFormData) { // 如果校驗通過,拼接子組件數據進行提交 const mainFormData = { ...baseFormData, ...coopFormData } // 提交數據 await saveApi(mainForm) this.$message.success('保存成功!') } } } } </script>
子組件負責處理自己的內容,同時提供方法給父組件調用,在方法裡進行校驗,校驗通過後再返回自身的表單數據給父組件。
// 子組件示例:base-form.vue <template> <el-form ref="ruleForm" :model="form" :rules="rules"> </el-form> </template> <script> export default { data() { return { form: { // ... }, rules: { // ... } } }, methods: { // 提供給父組件的方法並返回表單數據 validate() { return new Promise(resolve => { this.$refs['ruleForm'].validate(valid => { // 校驗通過返回表單數據,反之,返回null if (valid) { resolve(this.form) } else { resolve(null) } }) }) } } } </script>
表單兄弟組件的數據通信問題
將大表單拆分後,有些時候兄弟組件間需要通信,例如coop-form裡的某個字段需要根據base-form的某個字段來決定是否必填。我通常選擇使用vuex解決,在base-form的值變化時將其保存到vuex裡,coop-form則可以從vuex裡獲取,然後進行自己的邏輯處理。
// vuex裡新建文件用來存放表單通信數據 // src/store/modules/formDta.js export default { namespaced: true, state: { natureEnterprise: '' }, mutations: { SET_NATURE_ENTERPRISE(state, payload) { state.natureEnterprise = payload } } } // src/store/index.js import Vue from 'vue' import Vuex from 'vuex' import formData from './modules/formData.js' Vue.use(Vuex) export default new Vuex.Store({ modules: { formData } })
// base-form.vue watch: { 'form.natureEnterprise': { handler(val) { // 將企業性質的值存儲到vuex裡 this.$store.commit('formData/SET_NATURE_ENTERPRISE', val) } } }
// coop-form.vue computed: { ...mapState('formData', [ 'natureEnterprise' ]), rules() { return { address: [ { required: this.natureEnterprise === 1, message: '註冊地址不能為空', trigger: 'change' } ] } } }
以上就是vue開發中後臺系統復雜表單優化技巧的詳細內容,更多關於vue後臺系統復雜表單優化的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 詳談vue中的rules表單驗證(常用)
- antd vue v-decorator的取值與賦值問題
- Vue之ElementUI Form表單校驗
- vue表單驗證rules及validator驗證器的使用方法實例
- Vue使用antd中input組件去驗證輸入框輸入內容(rules 案例)