vue: 动态表单实现(多问题线)
之前写了一篇单问题线,这次写的是多问题线的逻辑思想。
如图,所谓的多问题线就是若问题块1的select1选了A,select2选了A,则会出现问题块3和问题块5,此时问题块3和问题块5是同级的,且不在一个问题线上,所以该次答题,至少有两条线上的答案需要获取。
这种情况下,上次的逻辑思想就无法解决该情况,就有了一个新的解决思路来解决,并且能解决多问题线的思路必能解决单问题线的问题。
需求需要解决的点:
- 逻辑结构不定,为后端提供
- 层级不定,由逻辑结构决定
- 填到最下面的叶子结点后,获取全部用户所填有效的问题结果
- 有创建和编辑功能,利用答案,反铺该答案所对应的表单
解决思路:
创建3个组件:
- index组件:整个表单
主要逻辑:
标示自己的父问题状态
铺页面:
循环逻辑结构数组,若fa为null或rule[fa].ans的答案等于faV时展示
提交答案:
循环逻辑结构数组,若fa为null或rule[fa].ans的答案等于faV时,获取答案
逻辑结构样例:
rule:[{
type: 'select',
name: 'w1',
label: '问题1',
ans: null,
fa: null,
content: [{
value: 'w11',
label: '问题1-答案1',
}, {
value: 'w12',
label: '问题1-答案2',
}]
}, {
type: 'select',
name: 'w2',
label: '问题2',
ans: null,
fa: 0,
faV: 0,
content: [{
value: 'w21',
label: '问题2-答案1',
}, {
value: 'w22',
label: '问题2-答案2',
}]
}]
对象属性 | 描述 |
---|---|
type | 问题类型 |
name | ans对象中该答案所对应的键 |
ans | ans对象中该答案所对应的值 |
label | 页面展示文字 |
fa | 该问题的先置问题的index值,若没有则为null |
faV | 该问题的先置问题所对应的答案,若没有则为null |
content | 问题为select的时候,下拉框内容 |
缺点:
逻辑结构的数组可读性差,规范要求严格(努力完善中)
局部代码:
<template>
<el-form :label-width="'150px'" label-position="right" >
<template v-for="(item, index) in rule">
<el-form-item
:key="index"
:label="item.label ? item.label: ''"
style="width: 100%"
v-if="item.type == 'select' && ((!item.fa && item.fa != 0) || rule[item.fa].ans == item.faV)"
>
<el-select v-model="item.ans" placeholder="请选择">
<el-option v-for="(option, option_index) in item.content" :key="option.label" :label="option.label" :value="option_index"></el-option>
</el-select>
</el-form-item>
<el-form-item
:key="index"
:label="item.label ? item.label: ''"
style="width: 100%"
v-if="item.type == 'textarea' && ((!item.fa && item.fa != 0) || rule[item.fa].ans == item.faV)"
>
<el-input type="textarea" v-model="item.ans"></el-input>
</el-form-item>
</template>
<el-form-item>
<div style="text-align:center; width: 500px;">
<el-button size="small" type="primary" style="margin-right: 50px;" @click="submitAns">确定</el-button>
<el-button size="small">取消</el-button>
</div>
</el-form-item>
</el-form>
</template>
<script>
import limitLevel from './LimitLevel';
import {
deepClone
} from '../../utils/utils'
let self = null;
export default {
components: {},
data() {
return {}
},
created() {
self = this;
},
props: ['rule'],
methods: {
submitAns() {
let ans = {};
for(let i = 0; i < this.rule.length; i++) {
let item = this.rule[i];
if((!item.fa && item.fa != 0) || this.rule[item.fa].ans == item.faV) {
if (!item.ans && item.ans != 0) {
this.$message({
type: "warning",
message: "请检查您的" + item.label + "是否填写"
});
return false;
}
ans[item.name] = item.ans;
}
}
console.log(ans);
}
}
}
</script>
最后:最终这种的解决方案并不满意,若有其他思路或改进方法,请指教,谢谢