Вложенные данные форм

Vuetify предоставляет мощный набор компонентов для построения форм с глубокой структурой данных, что позволяет эффективно управлять сложными объектами и массивами внутри Vue-приложения. Для работы с вложенными формами важно понимать, как компоненты Vuetify взаимодействуют с двусторонней привязкой (v-model) и как управлять вложенными объектами в реактивном состоянии.


Привязка вложенных объектов

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

data() {
  return {
    form: {
      user: {
        name: '',
        email: ''
      },
      address: {
        city: '',
        postalCode: ''
      }
    }
  }
}

Компоненты формы могут быть связаны с вложенными свойствами через v-model с точечной нотацией:

<v-text-field
  v-model="form.user.name"
  label="Имя"
/>
<v-text-field
  v-model="form.user.email"
  label="Email"
/>
<v-text-field
  v-model="form.address.city"
  label="Город"
/>
<v-text-field
  v-model="form.address.postalCode"
  label="Почтовый индекс"
/>

Это обеспечивает автоматическую реактивность: изменения в полях сразу отражаются в объекте form.


Динамические массивы объектов

Для вложенных массивов объектов используется v-for с v-model, что позволяет создавать динамические формы, где количество элементов может изменяться:

data() {
  return {
    form: {
      contacts: [
        { type: '', value: '' }
      ]
    }
  }
}
<div v-for="(contact, index) in form.contacts" :key="index">
  <v-text-field
    v-model="contact.type"
    label="Тип контакта"
  />
  <v-text-field
    v-model="contact.value"
    label="Значение контакта"
  />
  <v-btn icon @click="removeContact(index)">
    <v-icon>mdi-delete</v-icon>
  </v-btn>
</div>
<v-btn @click="addContact">Добавить контакт</v-btn>
methods: {
  addContact() {
    this.form.contacts.push({ type: '', value: '' });
  },
  removeContact(index) {
    this.form.contacts.splice(index, 1);
  }
}

Использование v-model с глубокими объектами

Vuetify поддерживает двустороннюю привязку для вложенных данных, но при глубокой вложенности стоит учитывать реактивность Vue. Для надежного отслеживания изменений рекомендуется использовать Vue.set или методы обновления массива:

updateNestedField(path, value) {
  const keys = path.split('.');
  let obj = this.form;
  for (let i = 0; i < keys.length - 1; i++) {
    obj = obj[keys[i]];
  }
  this.$set(obj, keys[keys.length - 1], value);
}

Это позволяет динамически изменять вложенные свойства и гарантирует реактивность при обновлении.


Валидация вложенных данных

Vuetify предоставляет возможность валидации через свойство rules. Для вложенных объектов правила можно определять локально для каждого поля:

data() {
  return {
    form: {
      user: { name: '', email: '' }
    },
    rules: {
      required: value => !!value || 'Поле обязательно',
      email: value => /.+@.+\..+/.test(value) || 'Неверный формат email'
    }
  }
}
<v-text-field
  v-model="form.user.email"
  label="Email"
  :rules="[rules.required, rules.email]"
/>

Для массивов объектов валидацию можно проводить при добавлении или перед отправкой формы, перебирая все элементы массива.


Компоненты для сложных вложенных структур

Vuetify предлагает ряд компонентов, упрощающих работу с вложенными данными:

  • v-combobox и v-autocomplete для выбора из вложенных списков.
  • v-checkbox-group и v-radio-group для группировки вложенных опций.
  • v-expansion-panels для визуального разделения вложенных секций формы.
  • v-card и v-card-text для структурирования сложных форм с повторяющимися блоками.

Пример вложенной карточки для контактов:

<v-expansion-panels>
  <v-expansion-panel
    v-for="(contact, index) in form.contacts"
    :key="index"
  >
    <v-expansion-panel-header>Контакт {{ index + 1 }}</v-expansion-panel-header>
    <v-expansion-panel-content>
      <v-text-field v-model="contact.type" label="Тип"/>
      <v-text-field v-model="contact.value" label="Значение"/>
    </v-expansion-panel-content>
  </v-expansion-panel>
</v-expansion-panels>

Связывание с Vuex или внешними данными

Вложенные формы Vuetify легко интегрируются с Vuex. Для обновления состояния Vuex можно использовать computed свойства с геттером и сеттером:

computed: {
  formData: {
    get() {
      return this.$store.state.form;
    },
    set(value) {
      this.$store.commit('updateForm', value);
    }
  }
}

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


Практические рекомендации

  • Использовать точечную нотацию v-model для вложенных полей.
  • Для массивов объектов всегда применять методы push, splice и Vue.set для сохранения реактивности.
  • Валидацию проводить локально на каждом поле и дополнительно при отправке формы для массивов.
  • Для визуального разделения вложенных блоков применять v-card и v-expansion-panel.
  • При работе с глобальным состоянием через Vuex использовать computed-свойства с сеттерами для двусторонней привязки.

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