«Эти вещи на переднем крае» развивают динамические формы от 0 до 1.

внешний интерфейс

Шуцзян надеется доставить удовольствие от внешнего интерфейса всем. Эта статья была включенаGitHub.com/маленькое дерево М…звездочка если хочешь ✨

Граница: в фоновом режиме много формы заявки нуждается в левой форме, есть правосторонняя форма, бесконечная, если один шаблон написать, написать не только много времени, но и то, что шумиха, так что на этот раз вы будете поди представь, что нет возможности заменить рукописный шаблон формы тривиальным способом ведения дел? Так что форма «без», а не вне линии и позволяет легко решить форму формы, больше не беспокойтесь о форме. Ответ: динамическая форма

1. Традиционные шаблоны форм

Что нужно для формы? Несомненно, он включает в себя сбор, проверку и отправку данных формы.Давайте рассмотрим следующую форму, основанную на библиотеке компонентов iview.

Эта простая форма, если свернуть вручную трафарет, часть трафарета показана на следующем 👇

Определите и проверьте логику инициализации данных, чтобы отправить следующие

Вышеупомянутое завершает форму со сбором данных, проверкой, отправкой и воспроизведением, но возникает и соответствующая проблема.Использование шаблона здесь не лучший выбор.Код слишком многословен и есть повторяющиеся коды.Несколько форм или даже больше , надо ли писать много кода для поддержки таких форм, не будет ли это слишком избыточно, давайте сегодня введем нашего главного героя: динамические формы, посмотрим как заставить его "двигаться" 💃 вставай

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

2.1 Форма, которую я ожидаю

Форма, которую я ожидаю, может быть настроена, и соответствующая форма создается динамически через JSON. Компоненты, задействованные в форме (такие как ввод, выбор), могут быть отображены путем получения конфигурации JSON. Шаблон, упомянутый в предыдущем разделе «Визуализация», явно не подходит для этой сцены.Хотя vue официально рекомендует использовать шаблоны для создания вашего шаблона в большинстве случаев, в некоторых сценах все же необходимо использовать функцию рендеринга renderОфициальная документация нажмите на меня👈

2.2 О функциях рендеринга

Давайте сначала посмотрим на этот пример: функция mount Vue.js визуализирует функцию узла VNode, сгенерированную h(), в реальный узел DOM и монтирует его на корневом узле.

этоh()Является функцией природы функции CAREEDEEDEDED, функция этой роли состоит в том, чтобы генерировать узел VNODE (виртуальный узел), он не является фактическим элементами DOM. Называется CreateenDeScriptionscription (создайте описание узла), мы передадим информацию, которую он содержит, чтобы сказать, какие узлы должны быть отображены на странице Vue, а затем можно отследить DOM Diff Algorith

Расширение: вам может быть интересно, почему это называетсяh()函数, вместоcreateElement()Сокращенное названиеc()

h происходит от первой буквы гиперскрипта, самое оригинальное определение — «Создать гипертекст с помощью JavaScript», а гипертекст происходит от знакомого HTML — это аббревиатура языка гипертекстовой разметки (язык гипертекстовой разметки), поэтому можно понять, что гиперскрипт относится к Генерировать HTML-скрипт

Функция createElment принимает три параметра, а именно:

  • Параметр 1: имя метки, опционный объект компонента, функция и т.д. (обязательно);
  • Параметр 2: Установить стиль, свойства, параметры передаваемого компонента, события привязки и т.д. этого объекта (необязательно);
  • Параметр 3: Другие узлы под этим узлом, то есть дочерние виртуальные узлы, могут быть в виде строк или массивов, и их также необходимо создавать с помощью createElement.

Ниже приведен простой пример, иллюстрирующий использование функции рендеринга👇.

Результат рендеринга шаблона в приведенном выше примере является то же самое, что для рендеринга рендеринга функций. Конечно, шаблон по существу скомпилирован через компиляцию для получения функции рендеринга.render(), так что на самом деле функция рендеринга более эффективна, быстрее и сокращает время компиляции.Для компиляции вы можете прочитать эту статьюПроцесс компиляции Vue, скомпилированный темплейтом в функцию рендеринга

Разница между рендерингом функции рендеринга и шаблоном шаблона

  • render(high) более эффективен, чем tempate(low).
  • Шаблон прост, и вы можете интуитивно увидеть, что контент хочет выразить, но он недостаточно гибок; функция рендеринга рендеринга создает VNode путем createElement, что подходит для разработки компонентов с сильной повторяемостью.

Завершите функцию рендеринга по запросу, а затем познакомьтесь с идеей динамических форм.

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

Здесь используется динамическая форма, основанная на библиотеке компонентов iview. Все созданные компоненты реализованы на основе iview. Ниже приведена конкретная блок-схема.

3.1 Содержание конфигурации формы конфигурации

Я использую пример из первого раздела для настройки конфигурации формы в формате JSON (поскольку файл конфигурации слишком длинный, вместо этого используйте текст)

const formOption = {
  ref: 'formValidate',
  style: { //表单样式,非必须
    width: '300px',
    margin: 'auto',
  },  
  className: 'form',
  formProps: { //非必须
    'label-width': 80,
  },
  formData: {//所要监听的表单字段数据,必须
     name: '',
     city: '',
     sex: 'male',
  },
  formItem: [ //iview form表单的每个formItem,必须
    {
      type: 'input',
      label: '名称', //对应formItem的label
      key: 'name', //key对应formData中的字段
      props: {
        placeholder: '请输入名称',
      },
      rules: {  //表单检测规则,非必须
        required: true,
        message: '请填写名称',
        trigger: 'blur',
      },
    },
    {
      type: 'select',
      label: '城市', //对应formItem的label
      key: 'city', //key对应formData中的字段
      props: {
        placeholder: '请输入名称',
      },
     children: [{ label: 'xml', value: '1' },
        { label: 'json', value: '2' },
        { label: 'hl7', value: '3' }
      ],
      rules: {  //表单检测规则,非必须
        required: true,
        message: '请选择城市',
        trigger: 'blur',
      },
    }, 
    {
      type: 'radioGroup',
      key: 'type',
      label: 'sex',
      children: [
        {
          text: 'female',
          label: 'female',
        },
        {
          text: 'male',
          label: 'male',
        },
      ],
      events: {
        'on-change': (vm, value) => {
          vm.$emit('on-change', value);
        },
      },
    }
  ],
  events: events('formValidate'),//表单按钮组                                       
}

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

3.2 Функция рендеринга визуализирует компонент

В первом примере используются компоненты формы, такие как Input, Select, radioGroup и formItem. это функции рендеринга, которые определяют их соответственно

  • Выкрывать API для рендеринга разных компонентов
  • Функция рендеринга входных компонентов

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

function generateInputComponent(h, formData = {}, obj, vm) {
    const key = obj.key? obj.key : ''
    let children = []

    if (obj.children) { //input有子集,走这里
        children = obj.children.map(item => {
            let component
            if (item.type == 'span') {  //复合型输入框情况                                       
                component = h('span', {
                    slot: item.slot
                }, [item.text])         
            } else {
                let func = componentObj[item.type]
                component = func? func.call(vm, h, formData, item, vm) : null
            }
            return component
        })
    }

    return h('Input', {
        props: {
            value: key? formData[key] : '',
            ...obj.props
        },
        style: obj.style,
        on: {
            ...translateEvents(obj.events, vm), //时间绑定
            input(val) {
                if (key) {
                    formData[key] = val
                }
            }
        },
        slot: obj.slot                                                                 
    }, children)
}
 //事件bind
function translateEvents(events = {}, vm, formData = {}) {
    const result = {}
    for (let event in events) {
        result[event] = events[event].bind(vm, vm, formData);
    }

    return result 
}                  
  • Выберите функцию рендеринга компонента
function generateSelectComponent(h, formData = {}, obj, vm) {
    const key = obj.key? obj.key : ''

    let components = []

    if (obj.children) {
        components = obj.children.map(item => {
            if (item.type == 'optionGroup') {
                return h('OptionGroup', {
                    props: item.props? item.props : item
                }, item.children.map(child => {
                    return h('Option', {
                        props: child.props? child.props : child
                    })
                }))
            } else {
                return h('Option', {
                    props: item.props? item.props : item
                })
            }
        })
    }

    return h('Select', {
        props: {
            value: formData[key],
            ...obj.props
        },
        style: obj.style,
        on: {
            ...translateEvents(obj.events, vm),
            input(val) {
                if (key) {
                    formData[key] = val
                }
            }
        },
        slot: obj.slot
    }, components)
}

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

  • генерация кнопки событий
function generateEventsComponent(h, formData = {}, obj, vm) {
    const components = [];
    if(obj.submit) {
        const submit = h('Button', {
            props: obj.submit.props,
            style: obj.submit.style,
            class: obj.submit.className,
            on: {
                click() {
                   //提交前校验
                    vm.$refs[obj.ref].validate((valid) => {
                        if (valid) {
                            obj.submit.success.call(vm, formData, vm)
                        } else {
                            obj.submit.fail.call(vm, formData, vm)
                        }
                    })
                }
            }
        }, [obj.submit.text])

        components.push(submit)
    }
    if (obj.reset) {
        const reset = h('Button', {
            props: obj.reset.props,
            style: {
                ...obj.reset.style,
            },
            class: obj.reset.className,
            on: {
                click() {
                    vm.$refs[obj.ref].resetFields() //重置表单
                    obj.reset.success.call(vm, formData, vm); 
                }
            }
        }, [obj.reset.text])

        components.push(reset)
    }

    return h('div',{
        class: 'vue-events',
        style: {
            ...obj.style
        }
    }, components)
}
  • Определение компонента динамической формы formBuild

Чтобы реализовать логику динамической генерации компонентов, на данный момент вам нужна запись (formBuild.js), которая должна отображать соответствующие компоненты в соответствии с конфигурацией, а также генерировать и объединять их в окончательную форму.

// form-build.js
import componentObj from './utils'

export default {
    props: {
        options: {
            type: Object,
            required: true
        },
    },
    render(h) {
        const options = this.options
        const formData = options.formData
        
        if (!options.formItem) {
            return h('div')
        }

        const components = options.formItem.map(item => {
            let func = componentObj[item.type]
            let subComponent = func? func.call(this, h, formData, item, this) : null
            let component = componentObj.formItem(h, item, subComponent, formData)
            return componentObj.col(h, item, component)
        })

        const childComp = [];

        const fromComp = h('Form', {
                ref: options.ref,
                style: options.style ? options.style : '',
                props: {
                    model: formData,
                    ...options.formProps
                },
                class: 'vue-generate-form'
            }, [
                h('Row', {
                    props: options.rowProps
                }, components)
           ]);
        
        childComp.push(fromComp);

        if (options.events) {
            const eventComo = componentObj.events(h, formData, obj.events , vm)                         
          childComp.push(eventComp)
        }
        return h('div', [childComp]);
    }
}

Вам также необходимо определить установку плагина vue

2.3 Как использовать

  • Меры предосторожности
  1. Некоторые компоненты (например, кнопка) iview не предоставляют что-то вродеon-clickтакое событие. Вместо этого вы можете использовать собственные события элемента DOM, например.click
  2. Все данные формы должны быть определены в formData

4. Резюме

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

  • Как поддерживать конфигурацию динамической формы для нескольких библиотек компонентов пользовательского интерфейса?

Вы можете обратиться к тому, как реализовано создание форм с открытым исходным кодом (поддерживает 3 фреймворка пользовательского интерфейса: Iview, ElementUI, Ant-design-vue).библиотека инструментов для создания формы

  • Как разработать инструмент динамической формы для онлайн-редактирования и настройки?

Инструмент визуального дизайна формы также очень ароматный, и заинтересованная детская обувь может понятьvue-ele-form-generator

Источник идей для статьи:vue-form-make

Прошлые статьи