Как создать форму на Vue на основании полученного config с JSON в виде дерева компонентов

Ответ

Для создания формы на Vue по конфигу JSON можно использовать динамические компоненты. Вот пример:

<template>
  <form @submit.prevent="handleSubmit">
    <component
      v-for="(field, index) in formConfig.fields"
      :key="index"
      :is="field.component"
      v-model="formData[field.name]"
      v-bind="field.props"
    />
    <button type="submit">Submit</button>
  </form>
</template>

<script>
export default {
  props: ['formConfig'],
  data() {
    return {
      formData: {}
    }
  },
  created() {
    this.formConfig.fields.forEach(field => {
      this.$set(this.formData, field.name, field.defaultValue || '')
    })
  },
  methods: {
    handleSubmit() {
      console.log('Form data:', this.formData)
    }
  }
}

Пример конфига:

{
  "fields": [
    {
      "component": "InputText",
      "name": "username",
      "props": {
        "label": "Username",
        "placeholder": "Enter username"
      }
    },
    {
      "component": "InputCheckbox",
      "name": "agree",
      "props": {
        "label": "I agree"
      }
    }
  ]
}

Ключевые моменты:

  • Используем <component> для динамического рендеринга
  • Инициализируем formData в created()
  • Обрабатываем submit формы
  • Конфиг содержит тип компонента, имя поля и пропсы

Ответ 18+ 🔞

Смотри, ну вот ты сидишь и думаешь: "Как бы мне такую форму на Vue сделать, чтобы она по какому-то конфигу JSON собиралась, а то мне каждый раз писать одно и то же — терпения ноль ебать". И ведь правда, зачем городить однотипный код, когда можно один раз настроить и потом только конфиги менять?

Так вот, слушай сюда, суть в чём. Берём динамические компоненты — это же просто пиздец как удобно, как будто конструктор Лего, только для фронтенда. Смотри, как это выглядит:

<template>
  <form @submit.prevent="handleSubmit">
    <component
      v-for="(field, index) in formConfig.fields"
      :key="index"
      :is="field.component"
      v-model="formData[field.name]"
      v-bind="field.props"
    />
    <button type="submit">Submit</button>
  </form>
</template>

<script>
export default {
  props: ['formConfig'],
  data() {
    return {
      formData: {}
    }
  },
  created() {
    this.formConfig.fields.forEach(field => {
      this.$set(this.formData, field.name, field.defaultValue || '')
    })
  },
  methods: {
    handleSubmit() {
      console.log('Form data:', this.formData)
    }
  }
}
</script>

А теперь, блядь, самое интересное — конфиг. Это просто JSON, который описывает, какие поля и как должны выглядеть. Представь, что ты не пишешь код, а заполняешь анкету, ёпта!

{
  "fields": [
    {
      "component": "InputText",
      "name": "username",
      "props": {
        "label": "Username",
        "placeholder": "Enter username"
      }
    },
    {
      "component": "InputCheckbox",
      "name": "agree",
      "props": {
        "label": "I agree"
      }
    }
  ]
}

Что тут происходит, спросишь ты? А я тебе объясню, как есть.

  1. Динамический рендеринг через <component> — это как волшебная палочка, блядь. Ты говоришь Vue: "Смотри, вот тебе имя компонента из конфига, вот тебе пропсы, а теперь, сука, собери это всё и покажи". И он собирает, потому что он не мудак.
  2. Инициализация formData в created() — это важно, ёпта! Нельзя просто так взять и положить данные в реактивный объект, если ключей изначально нет. Поэтому используем this.$set, чтобы Vue не обосрался и понял, что мы хотим следить за этими полями.
  3. Обработка сабмита — ну тут всё просто, в handleSubmit у тебя уже будет готовый объект formData со всеми значениями, которые пользователь навводил. Делай с ним что хочешь: отправляй на бэк, выводи в консоль, хоть на Луну передавай.
  4. Структура конфига — тут всё прозрачно, как слёзы ребёнка. component — это имя зарегистрированного глобально или локально компонента (типа InputText, InputCheckbox). name — это ключ, по которому значение будет лежать в formData. А props — это всё остальное, что нужно передать компоненту: label, placeholder, type, options — да что угодно, на что хватит фантазии.

И вот так, блядь, из кусочков конфига собирается целая форма. Хочешь добавить поле — просто дописываешь объект в массив fields. Хочешь убрать — хуяк, и удалил. Никакой возни с шаблоном. Красота, да и только, в рот меня чих-пых!

Главное, не забудь, что сами компоненты вроде InputText или InputCheckbox должны быть где-то зарегистрированы, иначе Vue будет смотреть на тебя, как баран на новые ворота, и ничего не отрендерит. Ну, ты понял, да?