[Серия Vue] Элегантно используйте vue для создания динамических форм (1)

Vue.js
[Серия Vue] Элегантно используйте vue для создания динамических форм (1)

фон спроса

Идет удовлетворение спроса.В товаре сказано, что для этого спроса есть еще формы.На данный момент их 19.В дальнейшем формы могут быть добавлены и изменены. Как ответственный за front-end разработку в этот раз, когда я увидел такой спрос, я сердцем понял, что фронтенд этим не исчерпывается, во-первых, форм было много, и их нужно было менять. , Было бы утомительно поддерживать в будущем.

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

дизайн интерфейса данных

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

Приготовьтесь создать интерфейс формы (где поясняется поля):
  • idидентификатор поля формы
  • nameИмя поля формы (имя поля хранится в базе данных)
  • typeТип поля формы (раскрывающийся список select_item, строковый однострочный текст, несколько многострочных текстов, целое однострочное число, изображения для загрузки изображения)
  • titleКитайское имя поля формы (имя поля динамической формы)
  • prompt_msgкопия заполнителя для полей формы
  • selectObjКогда тип select_item, selectObj имеет значение, значение по умолчанию равно null
{
	"code": 0,
	"msg": "success",
	"data": {
		"list": [{
			"id": 10,
			"name": "check_type",
			"type": "select_item",
			"title": "审核类型",
			"prompt_msg": "请填写审核类型",
			"selectObj": [{
				"id": 1,
				"item": "预审核"
			}, {
				"id": 2,
				"item": "患者审核"
			}],
			"val": null,
			"rank": 0
		}, {
			"id": 16,
			"name": "bank_branch_info",
			"type": "string",
			"title": "支行信息",
			"prompt_msg": "请填写支行信息",
			"selectObj": null,
			"val": null,
			"rank": 0
		},  {
			"id": 19,
			"name": "project_content",
			"type": "multiple",
			"title": "项目内容",
			"prompt_msg": "请填写项目内容",
			"selectObj": null,
			"val": null,
			"rank": 0
		}, {
			"id": 22,
			"name": "project_extension_time",
			"type": "integer",
			"title": "项目延长时间",
			"prompt_msg": "请填写项目延长时间",
			"selectObj": null,
			"val": null,
			"rank": 0
		}, {
			"id": 24,
			"name": "images",
			"type": "images",
			"title": "图片",
			"prompt_msg": "请上传图片",
			"selectObj": null,
			"val": null,
			"rank": 0
		}]
	}
}

Рендеринг форм через динамические компоненты Vue

Теперь, когда документ интерфейса формы готов к созданию, как визуализировать динамическую форму? Существует 5 типов типов элементов для динамических форм, и в соответствии с этой категорией создается пять компонентов элементов.

1. Загрузите компонент изображения

Здесь используется компонент загрузки изображенияUploaderкомпоненты.

<template>
    <div class="default images">
        <div class="lable">{{ item.title }}</div>
        <div v-if="item.val === null" class="content">
            <Uploader 
                :max-num="8"
                :user-imgs="project_image"
                @change="onUploadProject"
            />
        </div>
        <div v-else class="img-wrap">
            <img v-for="(it, idx) in item.val" :src="it" :key="idx" @click="preview(idx, item.val)">
        </div>
    </div>
</template>
2. Компонент многострочного поля ввода

Многострочное поле ввода по умолчанию составляет 3 строки.

<template>
    <div v-if="item"  class="default multiple">
        <div class="lable">{{ item.title }}</div>
        <template>
            <textarea
                rows="3" 
                :placeholder="item.prompt_msg" 
                v-model="value" 
                :value="it.item">
        </template>
    </div>
</template>
3. Компонент раскрывающегося списка выбора

используя элемент-интерфейсel-select

<template>
    <div v-if="item" class="default select_item">
        <div class="lable select-lable">{{ item.title }}</div>
        <div class="content">
            <el-select
                v-model="value" 
                placeholder="请选择类型" 
                class="el-select-wrap" 
                size="mini"
                @change="onChangeFirstValue"
            >
                <el-option
                    v-for="it in item.selectObj"
                    :key="it.id"
                    :label="it.item"
                    :value="it.item">
                </el-option>
            </el-select>
        </div>
    </div>
</template>

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

Компоненты создаются для облегчения унифицированного управления этими пользовательскими компонентами. Импорт и экспорт компонентов в виде экспортного композита по умолчанию.

// 单行文本输入框组件
export { default as String } from './string.vue'  

// 单行数字输入框组件
export { default as Integer } from './integer.vue' 

// 多行文本输入框组件
export { default as Multiple } from './multiple.vue' 

// 下拉列表选择器组件
export { default as Select_item } from './select_item.vue' 

// 上传图片组件
export { default as Images } from './images.vue' 

Затем страница динамической формы единообразно вводится и отображается в виде динамических компонентов Vue.isСвойство является именем динамического компонента.

<template>
    <div class="g-container">
        <component 
            v-for="(item, number) in freedomConfig" 
            :key="item.name"
            :is="item.type" 
            :item="item" 
            :number="number" 
            @changeComponent="changeComponentHandle"
        ></component>
    </div>
</template>

<script>
    import * as itemElements from '../../components/itemElement'
    
    export default {
        components: itemElements,
    }
</script>

После выполнения вышеперечисленного отображается динамическая форма. Форма создается динамически, как выполнить проверку формы и сводку данных формы?

сводка данных формы

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

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

data() {
    return {
        value: ''
    }
},
watch: {
    value(v, o) {
        this.throttleHandle(() => {
            this.$emit('changeComponent', {
                number: this.number,
                value: this.$data.value
            })
        })
    }
},

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

проверка формы

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

this.checkFrom(freedomConfig, preWordorderData).then(canSubmit => {
    canSubmit && postSubmitWorkorder(preWordorderData).then(res => {
        if (res.code === 0) {
            showLoading()
            this.$router.push(`/detail/${res.data.id}`)
        }
    })
})

checkFromДля нашего метода проверки выполните цикл по предварительно созданной форме, проверьте, имеет ли поле значение из данных, и выдайте всплывающее уведомление, если нет. и возвращаетpromise.resolve(false). Если все проверки пройдены, вернитесьresolve(true). Это делает функцию checkFrom асинхронной.

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

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