动态表单值的绑定与校验
我们都知道,为了让使用者更简单高效的开发,vue使用了表单元素双向绑定的模式。使用时每个表单元素都会在data中对应一个写死的变量,然后通过v-model进行绑定(v-model实现原理此处不做赘述,官网讲解很到位,面试基本会问到,请自行参考)。这种用法是最常用且易上手的,但是如果需求让我们做一个统一的组件,根据后端返回的json数据动态展示成相应的input、select、textarea、radio等元素,这种情况由于数据都是不确定的,之前的方法貌似有点行不通,怎么办呢?
假设后台返回数据大致如下:
"data": {
"username": {
"id": 1,
"label": "用户名",
"style": {
"width": "200px"
},
"required": true,
"validateType": "string",
"trigger": "blur",
"placeholder": "请输入用户名"
},
"password":{
"id": 2,
"type": "up-password",
"label": "密码",
"validateType": "",
"trigger": "blur"
},
"linkedA": {
"id": 2.01,
"label": "联动inputA",
"placeholder": "请输入",
"linked": "linkedB"
},
"linkedB": {
"id": 2.02,
"label": "联动inputB",
"placeholder": "请输入",
"required": true,
"beLinked": "linkedA"
},
"roles": {
"id": 2.1,
"type": "maya-check-list",
"label": "角色",
"validateType": "array",
"trigger": "change",
"candidates": [
{ "name": "管理员", "value": "admin" }, { "name": "顾客", "value": "customer" }, { "name": "用户", "value": "user" }, { "name": "客人", "value": "guest" }
]
},
...
}
1. 获取表单元素的绑定值
把后台数据中的key值作为表单v-model的值,根据不通过的类型初始化成空字符串或者空数组:
initFormModel (data) {
let formModel = {}
for(let item in data) {
formModel[item] = ""
if (data[item].type === 'maya-check-list' || data[item].type === 'maya-ui-select') {
formModel[item] = []
}
}
return formModel
}
2. 使用elmentUi,根据不同的元素类型展示对应的ui并进行值绑定
1,绑定:formItem.key中的key是后台数据中的key,通过v-model=“form[formItem.key]” 实现动态绑定;
2,校验: 使用el-form封装的表单校验,将el-form-item中prop对应成formItem.key,最后rules里面取后台数据指定的值即可。
大致代码如下:
<el-form ref="u-form" :model="form">
<el-col :span="colSpan" v-for="(data, i) in formData" :key="i" style="position: relative;">
<span v-for="(formItem, index) in data" :key="index" >
<el-form-item :label="formItem.label" label-width="25%" v-if="formItem.type != 'maya-config-group'"
:prop="formItem.key"
:rules="[
{ type: formItem.validateType, required: formItem.required, message: formItem.placeholder, trigger: formItem.trigger }
]">
<template v-if="formItem.type == 'maya-ui-select'">
<el-select v-model="form[formItem.key]" :placeholder="formItem.placeholder" size="small"
multiple clearable :disabled="formItem.disabled" :style="formItem.style">
<el-option :label="option.name" :value="option.id" v-for="(option,index) in formItem.model" :key="index"
:disabled="option.disable">
</el-option>
</el-select>
</template>
.....
<el-form-item/>
<el-col/>
<el-form/>
3. 后台只要按照对应的格式改变数据,前端不用做修改就能正确的显示ui了,最后除了实现正确绑定和校验外,还实现了动态展示一列还是两列,两列的时候第一列展示多少条数据的功能,最终效果如下:
单列展示如下:
两列展示如下:
根据后台数据动态展示列条数:
The end ~