首頁 > 軟體

vue開發中後臺系統複雜表單優化技巧

2022-07-07 14:01:21

引言

在中後臺系統的日常開發中,表單必不可少,當表單內容比較多,例如有上百個欄位(這一點都不誇張,血淋淋的現實)時,程式碼往往也變得複雜且難以維護,加上各種動態聯動的表單校驗,無疑讓我們的頁面開發過程雪上加霜,本文將結合自己平時的開發習慣,分享一下在大表單開發中如何處理複雜的表單校驗,以及如何對錶單進行拆分,減少單個檔案堆積過多的程式碼內容。

表單校驗

<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後臺系統複雜表單優化的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com