本篇文章给大家分享的是有关使用vue怎么构建一个动态表单,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
概述
后台管理系统里面有非常多的表单需求,我们希望能够通过写一个json格式的数据,通过vue的循环动态地去渲染动态表单。并且能够在外部得到渲染出来的表单的数据,可以对表单进行重置操作。我结合element ui的控件的下拉框,输入框,时间选择控件和vue-treeselect,做了一个动态表单。
v-model的理解
先简单讲一下vue-model是怎么玩的。其实vue-model相当于给表单元素传递一个value,外部监听input事件。所以我们自己封装表单组件的时候也是可以传递一个value值,监听input事件获取输入的值。
<input type="text" v-model="something"> <!--等价于--> <input type="text" v-bind:value="something" v-on:input="something = $event.target.value">
封装表单组件
组件最重要的开发思想就是设计好输入输出。这里就以下拉框组件为例吧。使用的是element ui的下拉框,进行一个简单封装。
输入:name:每个表单的数据标识,如区域编码输入框,父元素应该传递areaCode过来。
value: 表单选择/输入的值,从父元素获取后赋值给currentValue,通过监听父元素的值实现同步变
化。
options:下拉框要渲染的选项值,一般是个对象数组。
输出:onInputEvent,emit一个input事件,让父元素能够感知组件的数据变化。
也就是可以在组件使用的地方监听input事件
<template> <el-form-item :label="label"> <el-select v-model="currentValue" @input="onInputEvent"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> </template> <script> import formMixins from '../../../mixins/form-model' export default { name: "SelectList", props: ['name', 'label', 'value','options'], mixins: [formMixins], data() { return { currentValue: this.value } }, methods: { onInputEvent(value) { this.$emit('input', this.name, value); } }, watch: { value(val) { this.currentValue= val; } } } </script>
一点封装
由于每个表单组件都是监听父元素的value值变化,数据变化时都是触发onInputEvent并执行this.$emit('input'),所以我们可以把这部分内容抽取出来放在mixins里面。
form-model.js
export default { props: ['name', 'value'], data () { return { currentValue: this.value }; }, methods: { onInputEvent(value) { this.$emit('input', this.name, value); }, reset() { this.currentValue = ""; } }, watch: { value (val) { this.currentValue = val; } } };
然后我们的下拉框组件就可以少写一些共用的代码,直接用 mixins: [formMixins]
<template> <el-form-item :label="label"> <el-select v-model="currentValue" @input="onInputEvent"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> </template> <script> import formMixins from '../../../mixins/form-model' export default { name: "SelectList", props: ['name', 'label', 'value', 'options'], mixins: [formMixins], data() { return { currentValue: this.value } } } </script>
动态生成表单
这里主要是根据配置的数据,循环生成表单组件。默认提供提交和重置按钮,如果不需要可以通过slot传递其他操作按钮。这里的要点主要有:
监听表单组件的数据变化:
每个表单组件都有一个name标识它的业务含义,绑定的数据也是formData[field.name],@input事件传递updateForm,在updateForm里面更新this.formData[name],保证了this.formData里面的数据是和表单组件选择/填写的内容一致。
重置时改变表单组件的数据:
因为组件内部会监听父元素的value,所以这里只要清空this.formData的值,组件内部的数据也会跟着清空。
<template> <div> <el-form :inline="true" ref="form" :model="formData" class="demo-form-inline"> <el-col :span="field.cols" v-for="(field, index) in config.fieldsConfig" v-bind:key="index"> <component :key="index" :is="field.fieldType" :label="field.label" :value="formData[field.name]" :multiple="field.multiple" @input="updateForm" v-bind="field" :options="field.options" :ref="field.name" > </component> </el-col> <slot name="buttons"> <el-button type="primary" @click="submit" size="small">{{onSubmitText}}</el-button> <el-button type="default" @click="reset" size="small">{{onResetText}}</el-button> </slot> </el-form> </div> </template> <script> import SelectList from './basicComponent/SelectList' import TextInput from './basicComponent/TextInput' import TimeSelector from './basicComponent/TimeSelector' import SelectTree from './basicComponent/SelectTree' import StaffSelectPopedit from './businessComponent/StaffSelectPopedit' export default { name: "FormGenerator", components: { SelectList, TextInput, TimeSelector, SelectTree, StaffSelectPopedit}, props: ["config", "value"], data() { return { formData: this.value, onSubmitText: this.config.buttons.onSubmitText || '提交', onResetText: this.config.buttons.onResetText || '重置' } }, methods: { updateForm(fieldName, value) { this.formData[fieldName] = value; }, submit() { this.$emit("submit"); }, reset() { for(var name in this.formData) { if(typeof this.formData === "String") { this.formData[name] = ""; } else { this.formData[name] = null; } } } } } </script>
业务使用的地方
像下拉框的选择数据,这些应该是后台渲染的,所以我们暂时用setTimeout模拟一下。感觉这里this.config.fieldsConfig[4].options写的不太优雅,依赖于配置数据的顺序肯定不是啥好事情。求大神指点。
<template> <div> <form-generator :config="config" @submit="getFormData" v-model="formData" > </form-generator> </div> </template> <script> import FormGenerator from '../components/form/FormGenerator' export default { name: "FormGeneratorDemo", components: { FormGenerator }, created () { this.queryOrderType(); this.queryAreaTree(); }, data() { return { formData: { orderCode: "", orderType: "", beginTime: "", endTime: "", area: [], staff:"" }, config: { fieldsConfig: [ { name: 'orderCode', label: '定单编码', fieldType: 'TextInput', cols: 8 }, { name: 'orderType', label: '定单类型', fieldType: 'SelectList', options: [], cols: 8 }, { name: 'beginTime', label: '开始时间', fieldType: 'TimeSelector', cols: 8 }, { name: 'endTime', label: '结束时间', fieldType: 'TimeSelector', cols: 8 }, { name: 'area', label: '区域', fieldType: 'selectTree', options: [], multiple: true, cols: 8 }, { name: 'staff', label: '人员选择', fieldType: 'StaffSelectPopedit', cols: 8 } ], buttons: { onSubmitText: '提交', onResetText: '重置' } } } }, methods: { getFormData() { console.log(this.formData); }, queryOrderType() { setTimeout(() => { this.config.fieldsConfig[1].options = [ { label: 'select1', value: 'key1'}, { label: 'select2', value: 'key2'}, { label: 'select3', value: 'key3'} ]; }, 100) }, queryAreaTree() { this.config.fieldsConfig[4].options = [ { id: 'a', label: 'a', children: [{ id: 'aa', label: 'AA', }, { id: 'ab', label: 'AB', }], }, { id: 'b', label: 'B', }, { id: 'c', label: 'C', } ] } } } </script>
以上就是使用vue怎么构建一个动态表单,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。