一、项目背景
需要一个提交表单,内容经常增减变动。于是设计一套后端提供配置, 前端自动生成的一个组件。前后端都比较方便,前端不需要频繁变动,后端也只需配置即可。
联动需求:后续加上联动需求
举例: xx 省 xxx市 xxx区
联级数据,三个下拉,需要获取得到前一个值才能渲染后面的下拉框。
二、思路
初始设计一套,for循环完事了。后续需要联级,没办法只能想到递归,使用组件调用自己的方式。
A组件中不断去调用A组件,将需要递归的一层传进去再次渲染
三、问题
遇到问题有几个
1、数据绑定问题,最高层的数据传入后,后续随着递归的进行,后面的数据与最高层数据丢失联系,导致无法获取值,以及绑定。
2.表单样式问题(待解决,解决完再更新)
四、代码解决办法
<template>
<div>
<div
v-for="value in controls"
:key="value.label"
class="form-item"
>
<div class="item-label">{{ value.label }}:</div>
<div class="item-control">
<!-- switch -->
<el-switch
v-if="value.type == 'switch'"
v-model="value['default']"
active-color="#13ce66"
inactive-color="#DCDFE6"
></el-switch>
<!-- /switch -->
<!-- input -->
<el-form-item
:error="value['error'] != undefined ? value['error'] : ''"
>
<el-input
v-if="value.type == 'input' && value.datatype !== 'int'"
v-model="value['default']"
@input="hasError(value)"
></el-input>
<el-input
v-if="value.type == 'input' && value.datatype == 'int'"
v-model="value['default']"
oninput="this.value =value.replace(/[^\d^\.]+/g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.')"
@input="hasError(value)"
></el-input>
</el-form-item>
<!-- /input -->
<!-- select -->
<el-select
v-if="value.type == 'select'"
v-model="value['default']"
placeholder="choose"
>
<el-option
v-for="item in value.data"
:key="item.value"
:label="item.label"
:value="item.value"
:style="{ color: item.mode == 'dev' ? '#ccc' : null }"
>
</el-option>
</el-select>
<!-- /select -->
<!-- textarea -->
<el-input
v-if="value.type == 'textarea'"
v-model="value['default']"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="Please enter the content"
>
</el-input>
<!-- /textarea -->
</div>
<--! 关键代码>
<ParamsControls
:formData.sync="value[value['default']]"
:controls="value[value['default']]">
</ParamsControls>
</div>
</div>
</template>
<script lang="ts">
import {
Input,
Card,
Col,
Row,
Switch,
Button,
Select,
Option,
FormItem,
Form,
} from "element-ui";
import _ from "lodash";
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import Sortedbam from "../pages/PageSequencingTaskTS0216/custom-components/Sortedbam.vue";
@Component({
components: {
"el-card": Card,
"el-switch": Switch,
"el-button": Button,
"el-select": Select,
"el-input": Input,
"el-option": Option,
"el-form": Form,
"el-form-item": FormItem,
Sortedbam: Sortedbam,
ParamsControls: ParamsControls,
},
})
export default class ParamsControls extends Vue {
isLoading: boolean = false;
formData:object={};//关键!
@Prop()
controls!: object | undefined;
created() {
this.formData=this.controls||{}; //关键!
}
hasError(value: any) {
if (!value["default"] && value["error"] != undefined) {
value.error = "Not empty!";
} else if (value["default"] && value["error"] != undefined) {
value.error = "";
}
}
}
</script>
<style scoped lang="scss">
.form-item {
width: 50%;
display: grid;
grid-template-columns: 200px 1fr;
align-items: center;
padding: 10px 0;
.item-label {
text-align: right;
word-break: break-all;
}
.item-control {
padding: 0 20px;
max-width: 200px;
}
}
</style>
文件代码全部贴出,后续会更新一下
自己引用自己,再用父子双向绑定,迭代后所有的数据都绑定住了,这样就搞定了绑定问题。