Динамические формы

В библиотеке Naive UI динамические формы реализуются с помощью компонентов <n-form> и <n-form-item> в сочетании с реактивными структурами данных Vue. Динамическая форма — это форма, поля которой могут создаваться, изменяться или удаляться во время работы приложения в зависимости от состояния данных.

Для начала создаём реактивный объект, который будет хранить данные формы:

import { reactive } from 'vue'

const formData = reactive({
  fields: [
    { label: 'Имя', value: '', type: 'text' },
    { label: 'Возраст', value: '', type: 'number' }
  ]
})

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

  • label — отображаемый текст поля;
  • value — текущее значение поля;
  • type — тип поля ввода (text, number, email и др.).

Генерация формы на основе массива

Используя директиву v-for, можно создавать форму динамически:

<n-form :model="formData">
  <n-form-item
    v-for="(field, index) in formData.fields"
    :key="index"
    :label="field.label"
  >
    <n-input v-model="field.value" :type="field.type" />
  </n-form-item>
</n-form>

Здесь v-model обеспечивает двухстороннюю привязку данных. Любое изменение значения в поле автоматически обновляет объект formData.

Управление динамическими полями

Для добавления новых полей можно использовать метод, который модифицирует массив fields:

function addField(label, type = 'text') {
  formData.fields.push({ label, value: '', type })
}

Удаление поля осуществляется с помощью метода splice:

function removeField(index) {
  formData.fields.splice(index, 1)
}

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

Валидация динамических форм

Naive UI предоставляет встроенную систему валидации через свойство rules у <n-form>. Для динамических форм можно формировать правила программно:

import { reactive } from 'vue'

const rules = reactive({})

formData.fields.forEach((field, index) => {
  rules[`fields.${index}.value`] = [
    { required: true, message: `${field.label} обязателен` },
    { type: field.type === 'number' ? 'number' : 'string', message: `Неверный тип данных` }
  ]
})

Привязка правил к форме:

<n-form :model="formData" :rules="rules">
  <n-form-item
    v-for="(field, index) in formData.fields"
    :key="index"
    :label="field.label"
    :path="`fields.${index}.value`"
  >
    <n-input v-model="field.value" :type="field.type" />
  </n-form-item>
</n-form>

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

Реактивные изменения полей

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

function onUserTypeChange(type) {
  formData.fields = [
    { label: 'Имя', value: '', type: 'text' }
  ]
  if (type === 'employee') {
    formData.fields.push({ label: 'Должность', value: '', type: 'text' })
  } else if (type === 'student') {
    formData.fields.push({ label: 'Группа', value: '', type: 'text' })
  }
}

Такой подход позволяет создавать адаптивные формы, которые изменяются в реальном времени в зависимости от контекста.

Использование кастомных компонентов

Для более сложных форм возможно использование динамических компонентов внутри <n-form-item> с помощью <component :is="">:

<n-form-item
  v-for="(field, index) in formData.fields"
  :key="index"
  :label="field.label"
>
  <component :is="field.component" v-model="field.value" v-bind="field.props" />
</n-form-item>

Это позволяет интегрировать селекты, переключатели, чекбоксы и любые другие компоненты Naive UI, сохраняя при этом динамическую генерацию.

Сбор данных и отправка формы

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

const formRef = ref(null)

async function submitForm() {
  try {
    await formRef.value.validate()
    console.log('Данные формы:', formData)
  } catch (err) {
    console.error('Ошибка валидации:', err)
  }
}

Вместе с динамическими правилами валидации это обеспечивает полную безопасность и контроль над вводом данных.

Оптимизация и масштабирование

Для крупных проектов с множеством динамических форм рекомендуется:

  • Разбивать поля на логические блоки и использовать вложенные компоненты;
  • Генерировать правила валидации программно, чтобы не дублировать код;
  • Использовать реактивные вычисляемые свойства (computed) для зависимых полей, чтобы избежать избыточных перерендеров;
  • Применять ключи :key в v-for для корректного отслеживания динамических элементов при добавлении и удалении.

Такой подход позволяет создавать масштабируемые, гибкие формы, полностью интегрированные с экосистемой Naive UI.