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其它相關文章!

推薦閱讀: