В конце концов, веб-приложение (или любое другое программное обеспечение) выполняет одну задачу: позволяет пользователю читать и обновлять данные. Одна из задач, которую вы часто выполняете, - это создание форм, в которых пользователь может вводить или редактировать информацию. Это может быть очень утомительно и не очень СУХОЕ (не повторяйтесь), если в приложении есть несколько мест, где можно манипулировать одними и теми же данными.

Допустим, мы создаем пользовательскую форму на веб-сайте для домашних животных. Вы, вероятно, настроили бы форму примерно так:

<template>
  <div>
    <form>
      <div>
        <label>Username</label>
        <input
         v-model="username"
         placeholder="Enter Username"
         type="text"/>
      </div>
      <div>
        <label>How Many Pets Do You Have?</label>
        <input
         v-model="amountOfPets"
         placeholder="Tell us!"
         type="number"/>
      </div>
      <div>
        <label>What Is Your Favorite Pet Type?</label>
        <select v-model="favoritePetType">
          <option value="dogs">Dogs!</option>
          <option value="cats">Cats!</option>
          <option value="fish">Fish!</option>
          <option value="rodents">Rodents!</option>
          <option value="other">Something Else!</option>
        </select>
      </div>
      <div>
        <label>Do You Want To Recieve Pet News and Updates?</label>
        <input v-model="wantsEmailUpdates" type="checkbox"/>
      </div>
    </form>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        username: '',
        amountOfPets: null,
        favoritePetType: '',
        wantsEmailUpdates: false
      }
    }
  }
</script>

Это нормально, но нам нужно вручную создать каждое поле и смоделировать его. Если вы делаете это только один или два раза, это должно быть нормально. Но по мере роста вашего приложения вы можете создавать подобные формы с одинаковыми точными полями данных в разных местах. Допустим, у вас есть поле favouritePetType во многих местах, и вы решили добавить «рептилии» в качестве опции. Для этого вам нужно будет обновить множество файлов.

Лучшим способом является создание многократно используемого компонента ввода формы и объекта, в котором хранятся поля, которые вы используете в своем приложении, тип ввода, заполнитель и другие данные, участвующие в создании поля. Затем ваши формы могут просто отображать данные поля и иметь единый источник достоверной информации о том, какие данные должны содержать поля. Кроме того, вы можете сэкономить время на создании каждого из этих компонентов.

Ваш объект полей будет выглядеть примерно так:

const fields = {
  username: {
    label: 'Username',
    type: 'text',
    placeholder: 'Enter Username'
  },
  amountOfPets: {
    label: 'How Many Pets Do You Have?',
    type: 'number',
    placeholder: 'Tell Us!'
  },
  favoritePetType: {
    label: 'What Is Your Favorite Pet Type?',
    type: 'select',
    placeholder: '',
    options: [
      {
        type: 'dogs',
        label: 'Dogs!'
      },
      {
        type: 'cats',
        label: 'Cats!'
      },
      {
        type: 'fish',
        label: 'Fish!'
      }
      // ...etc
    ]
  },
  wantsEmailUpdates: {
    label: 'Do You Want To Receive Pet News and Updates?',
    type: 'checkbox'
  }
}

… И ваш компонент формы многократного использования будет выглядеть примерно так:

<template>
<div>
  <div>
      
      <label>{{ input.label }}</label>
   
       <select
        v-if="input.type === 'select'"
        :value="inputValue"
        @input="update($event.target.value)"
        >
        <option
          v-for="option in input.options"
          :value="option.type">
          {{ option.label }}
        </option>
      </select>
      <input
        v-else
        :type="input.type"
        :placeholder="input.placeholder"
        :value="inputValue"
        @input="update($event.target.value)"
       />
  </div>
</div>
</template>
<script>
  export default {
    props: ['input', 'inputValue'],
    methods: {
      update (value) {
        this.$emit('update', value)
      }
    }
  }
</script>

Теперь вы можете преобразовать исходную форму, чтобы она выглядела так:

<template>
  <div>
    <form>
      <ReusableInput
        v-for="(field, key) in userFields"
        :input="fieldData[key]"
        :inputValue="userFields[key]"
        @update="updateUserFields(key, $event)"
      >
      </ReusableInput>
    </form>
  </div>
</template>
<script>
  import ReusableInput from './ReusableInput'
  import fieldData from './fieldData'
  export default {
    components: {
      ReusableInput
    },
    data () {
      return {
        userFields: {
          username: '',
          amountOfPets: null,
          favoritePetType: '',
          wantsEmailUpdates: false
        }
      }
    },
    methods: {
      updateUserFields (field, value) {
        this.userFields[field] = value
      }
    }
  }
</script>

Как видите, мы включаем компонент ReusableInput всего один раз. Затем мы сопоставляем поля, которые нам нужны в этой конкретной форме, и передаем данные из главного списка formData. Мы также передаем входные данные, чтобы ими можно было манипулировать. Конечно, нам не хватает обработки ошибок и способов ее подключения к серверной части. Форма ReusableInput также поддерживает только ввод и выборку - вы, вероятно, захотите, чтобы она обрабатывала более широкий диапазон типов ввода, некоторые из которых могут включать настраиваемые подкомпоненты. Но что касается общей идеи, такой подход может сэкономить ваше время и сэкономить головную боль при работе с формами.

Наслаждаться!

Как вы поступали с компонентами формы? Поделитесь своими мыслями об этом подходе и альтернативах в комментариях.