温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用vue怎么构建一个动态表单

发布时间:2021-04-12 17:04:37 来源:亿速云 阅读:811 作者:Leah 栏目:web开发

本篇文章给大家分享的是有关使用vue怎么构建一个动态表单,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

概述

后台管理系统里面有非常多的表单需求,我们希望能够通过写一个json格式的数据,通过vue的循环动态地去渲染动态表单。并且能够在外部得到渲染出来的表单的数据,可以对表单进行重置操作。我结合element ui的控件的下拉框,输入框,时间选择控件和vue-treeselect,做了一个动态表单。

使用vue怎么构建一个动态表单

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怎么构建一个动态表单,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue
AI