1. ホーム
  2. Web プログラミング
  3. ジャバスクリプト
  4. javascriptのクラスライブラリ

Vue+ElementUIによる大規模なフォームの処理例

2022-01-13 21:21:02

最近、業務再編により、以前の超長文フォームのロジックに変更が増えたので、リファクタリングを計画しました(退社したバックエンドが書いたもので、コメントもなく、コンポーネントが4000行以上書いてあり、本当に大変でした)。読むのに便利なように、ここではプロジェクトを14個のコンポーネントに分割して合理化しました。

全体像 /{h3
  • 大きな帳票は、業務モジュールごとに分割
  • el-formが提供するvalidateメソッドで保存する(分割された各コンポーネントをループする)
  • mixin 各コンポーネントのコモン抽出(後のプロジェクトメンテナンスにも便利です)

スタート

フォーム1、フォーム2という2つのコンポーネントを分割する例です(読者の便宜を図るため、名前は伏せ字にしています)。

ここで、なぜref、モデルバインディング、フォームの2つのコンポーネントなのかは、後で説明します(後のメンテナンスを容易にするため)。

// form1 component
<template>
    <el-form
      ref="form"
      :model="form"
      label-width="10px"
    >
      <el-form-item label="name" prop="name">
          <el-input v-model="form.name" />
      </el-form-item>
    </el-form>
</template>
<script>
export default {
  name: 'Form1',
    props: {
      form: {}
  },
  data() {
    return {
      rules: {
        name: [
          { required: true, message: 'Please enter your name', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    // This is for the parent component to loop through the checksum calls
    validForm() {
        let result = false
        this.$refs.form.validate(valid => valid && (result = true))
        return result
    }
    // I also used another way to write it here, but the loop check is a promise object, there is a problem, hope the big guys point out a couple of things
    validForm() {
        // Obviously the output structure here is Boolean, but after the parent component loop call it's a promise type, need to convert it to work
        return this.$refs.form.validate().catch(e => console.log(e))
    }
  }
}
</script>
 
// form2 component
<template>
    <el-form
      ref="form"
      :model="form"
      label-width="10px"
    >
      <el-form-item label="age" prop="age">
          <el-input v-model="form.age" />
      </el-form-item>
    </el-form>
</template>
<script>
export default {
  name: 'Form2',
  props: {
      form: {}
  },
  data() {
    return {
      rules: {
        name: [
          { required: true, message: 'Please enter your age', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    // This is for the parent component to loop through the checksum calls
    validForm() {
        let result = false
        this.$refs.form.validate(valid => valid && (result = true))
        return result
    }
  }
}
</script>

親コンポーネントがどのように参照されているか見てみましょう

// parent component
<template>
    <div class="parent">
        <form1 ref="form1" :form="formData.form1" />
        <form2 ref="form2" :form="formData.form2" />
        <el-button type="primary" @click="save"> report error</el-button>
    </div>
</template>
<script>
... Omit the reference
export default {
    name: 'parent',
    ... Omit registration
    data () {
        return {
            formData: {
                form1: {},
                form2: {}
            }
        }
    },
}
</script>

formDataの属性名form1, form2はサブフォームコンポーネントのrefで使われているので、トラバースするときに順番に見つけて、以下のコードで保存関数を修正します。

methods: {
    save () {
        // The key value of each form object, which is the ref value of each form
        const formKeys = Object.keys(this.formData)
        // Execute each form's validation method
        const valids = formKeys.map(item => this.$refs[item].validForm())
        // Logic after all forms pass the validation
        if (valids.every(item => item)) {
          console.log(11)
        }
    }
}

コンポーネント ref と model の両方がフォームにバインドされている理由を解決します。

  • 比較の結果、form1 form2 は共通の props メソッドを持っていることがわかります。
  • それをMixinで抽出してみましょう
export default {
  props: {
    form: {
      required: true,
      type: Object,
      default: () => {}
    },
  },
  methods: {
    validForm () {
      let result = false
      this.$refs.form.validate(valid => valid && (result = true))
      return result
    }
  }
}

form1 form2 の minix を参照し、対応するコンポーネントの対応するプロパティとメソッドを削除します。

エンディング

  • オーバーサイズのフォームを解決するのは難しいので、ここではコンポーネントを分割しているだけです。
  • 部品間の連携も大きな難点なので、次回は完成後に発信します

今回はVue+ElementUIの大きなフォームへの対応例について紹介しましたが、より関連するVue+ElementUIの大きなフォームへの対応内容についてはBinaryDevelopの過去記事を検索するか、以下の関連記事を引き続き閲覧してください。