Vuejs+ElementUI实现可配置的动态表单配置

5,827 阅读2分钟

实现目标:将后台管理系统中的表单部分重新渲染实现成可配置的(通过数据库配置),动态的。需要支持系统中的所有附带搜索项的页面(如输入框、下拉框、日期、单选框等)

需求目标

  • 封装可复用的组件需要根据后台数据渲染搜索模块
  • 筛选条件需随配置表格列的内容可动态变化

方案

封装出公共搜索模块组件,使用与系统的各个有搜索功能的页面

将搜索、重置、收起功能放在一个组件DynamicForm内,将搜索项放在另一个组件DynamicFormItem。此处需要封装两个互为父子关系的组件。所需页面只是通过调用DynamicForm组件来展示form表单内容。

需要指定一个通用的配置信息的数据结构渲染组件页面。

数据结构

组件接受的数据如下:

与之前的原系统保持一致,渲染组件时请求获取下拉框的数据(包括请求接口返回的数据和获取的常量)

搜索栏中所需的数据格式

searchParams:搜索对象,以系统管理页面为例。

{
    currentPage:1,
    pageSize:10,
    employeeName: 'fei',
    userName:'h',
    sex:'SEX_MALE',
    deptId:'11',
    positionId:'987',
    userStatus:'USER_STATUS_FORBIDDER'
}

表单搜索栏配置所需的数据结构

config对象,描述当前页面的form表单情况,渲染实际展示的搜索栏。以管理系统通用的用户页面为例。

config:{
attrs: {
	'inline': false,
	'labelPostion': 'right',
	'labelWidth': '70px',
	'size': 'small',
	'stateIcon': true
  },
layout: [{
	attrs: {
		 gutter: 0
		},
	formItem: [{
		 itemAttrs: {
				'type': 'input',
				'label': '姓名',
				'disable': false,
				'readonly': false,
				'placeholder': '请输入姓名',
				'rules': [],
				'key': 'employeeName',
				'subtype': 'text',
				'value': ''
				}
			}]
	}, {
	attrs: {
		gutter: 0
		},
	formItem: [{
		itemAttrs: {
				'type': 'select',
				'label': '性别',
				'disable': false,
				'readonly': false,
				'placeholder': '请选择',
				'rules': [],
				'key': 'sex',
				'subtype': 'text',
				'value': '',
				'options': [], // 注意此处的数据             
			},
		},... ],
	}, {
	attrs: {
		gutter: 0,
		},
	formItem: [{
		itemAttrs: {
				'type': 'date',
				'label': '截止日期',
				'disable': false,
				'readonly': false,
				'placeholder': '请选择',
				'rules': [],
				'key': 'endDate',
				'value': '',
				'options': [], // 注意此处的数据
			},
		}, ...],
	},... ]
}

通用性问题

业务组件调用封装的组件

此处针对通用的用户页面来说,调用封装的组件

    <dynamic-form ref='dynamicForm' :config='config' v-model='object' 
            @putHandle='handleCollapse'            @searchHandleEvent='getListData(1)'     />
  • 搜索表单

通过v-for循环渲染不同搜索项,并且将原来的搜索事件,重置事件,收起事件进行原样移植

  • 控制渲染的搜索项label

根据后台接口返回的数据渲染搜索条件

搜索表单

封装的DynamicForm组件上绑定系统中已有的事件,搜索事件、重置事件、收起事件等

    <el-form-item v-for="con in config.layout" :key="con.key">
	<div v-for="item in con.formItem" :key="item.itemAttrs.key" class="item-width">
		<dynamic-form-item
			v-if="value[item.itemAttrs.key]!==undefined"
			:key="item.itemAttrs.key"
			:item="item.itemAttrs"
			v-bind="item.itemAttrs"
			:value="value[item.itemAttrs.key]"
			@input="handleInput($event,item.itemAttrs.key)"
		/>
	</div>
</el-form-item>
<el-form-item class="search_btn">
	<!-- 搜索按钮 -->
	<dr-btn-search @click="searchEvent"/>
	<!-- 重置按钮 -->
	<dr-btn-search-reset @click="reset"/>
	<!-- 收起按钮 -->
	<dr-btn-search-cancel @click="putArea"/>
</el-form-item>

注意此处的搜索参数与重置参数

搜索事件触发时调用父组件的搜索接口方法,根据this.object对象获取相应的参数

重置事件触发时只需要调用setDefaultValue 方法即可

收起事件触发时调用父组件的收起方法

控制渲染的搜索项,封装的DynamicFormItem组件

<template>
    <el-form-item :rules="Rules" :label="item.label" :prop="item.key" class="item-style">
		<dr-input v-if="item.type==='input' v-bind="$attrs" :type="item.type" 
		:placeholder="item.placeholder"
		:disabled="item.disabled"
		:readonly="item.readonly"
		maxlength="48"
		v-on="$listeners"/>
		<el-select v-else-if="item.type==='select' v-bind="$attrs"
		:multiple="item.multiple"
		:disabled="item.disabled"
		clearable
		v-on="$listeners">
			<el-option v-for="o in item.options" :key="o.key||o.id" 
			:label="o.label||o.lookupName" :value="o.value||o.lookupCode"/>
		</el-select>
		<el-date-picker v-else-if="item.type==='date' v-bind="$attrs" 
                :type="item.type"
		:placeholder="item.placeholder" clearable v-on="$listeners"/>
    </el-form-item>
</template>

后期扩展性

还可以扩展出checkbox,radio,time等