vue: 动态表单实现(单问题线)

vue: 动态表单实现(单问题线)

这个是工作中的一个需求,当然需求比较浅,适当的扩展实现了一下,写个博客记录一下当下的逻辑思想

vue: 动态表单实现(单问题线)_第1张图片
需求如上图,简单来说就是一个select选择不同的答案,后面可以会多出不同的题目。然后就是问题块的概念,一堆问题,这些问题同时间出现且没有先后顺序,则为一个问题块,一个问题块中的一个select的选择,可能触发另一个问题块的出现。

需求需要解决的点:

  1. 逻辑结构不定,为后端提供
  2. 层级不定,由逻辑结构决定
  3. 填到最下面的叶子结点后,获取全部用户所填有效的问题结果
  4. 有创建和编辑功能,利用答案,反铺该答案所对应的表单

解决思路:
创建3个组件:

  • index组件:该表单的入口
  • level组件:一个问题块
  • end组件:一个表单的最后,也就是提交步骤

铺页面:
在页面中向后端请求获取逻辑结构,将逻辑结构放入index组件,index组件拿到逻辑结构交给level组件,有level组件进行铺第一个根问题块,若问题选择,激活了另一个问题块,则level组件引用本身,循环该问题块,直至遇到‘end’标识符位置,展示提交按钮。

获取答案:
点击end组件的提交按钮,初始化ans的答案空对象,向该组件的父组件进行传值,传值包括ans答案及该组件的逻辑结构,父组件拿到值,将自己的答案添加到ans对象中去,并将自组件传来的逻辑结构放到自己逻辑结构中的child字段中去,再将ans对象和自己更新完的逻辑结构传向自己的父组件,反复操作,直到达到index组件,整理答案,传值页面,有页面展示和向后台传递ans对象。而更新完的逻辑结构也需交给后台保存,以供前台之后修改时恢复表单。
vue: 动态表单实现(单问题线)_第2张图片
逻辑结构样例:

         limitRule: [{
                type: 'select',
                name: 'wr1,
                label: '问题块根-问题1',
                ans: null,
                child: null,
                content: [{
                    value: 'wr11',
                    label: ''问题块根-问题1-答案1',
                    children: [{
                        type: 'select',
                        name: 'w11',
                        label: '问题块1-问题1',
                        ans: null,
                        child: null,
                        content: [{
                            value: 'w11',
                            label: '问题块1-问题1-答案1',
                            children: [{
                                type: 'end'
                            }],
                        }, {
                            value: 'w11',
                            label: '问题块1-问题1-答案2',
                            children: [{
                                type: 'select',
                                name: 'wa1',
                                label: '问题块a-问题1',
                                ans: null,
                                child: null,
                                content: [{
                                    value: 'wa11',
                                    label: '问题块a-问题1-答案1',
                                    children: null,
                                },{
                                    value: 'wa11',
                                    label: '问题块a-问题1-答案2',
                                    children: null,
                                }]
                            }, {
                                type: 'select',
                                name: 'wa2',
                                label: '问题块a-问题2',
                                ans: null,
                                child: null,
                                content: [{
                                    value: '问题块a-问题2-答案1',
                                    label: 'wa21',
                                    children: null,
                                },{
                                    value: '问题块a-问题2-答案1',
                                    label: 'wa22',
                                    children: null,
                                }]
                            }, {
                                type: 'end'
                            }],
                        }]
                    }]
                }, {
                    value: 'wr12',
                    label: '问题块根-问题1-答案2',
                    children: [{
                        type: 'select',
                        name: 'wb1',
                        label: '问题块b-问题1',
                        ans: null,
                        child: null,
                        content: [{
                            value: 'wb11',
                            label: '问题块b-问题1-答案1',
                            children: [{
                                type: 'textarea',
                                name: 'wb111',
                                label: '问题块b1-问题1',
                                ans: null,
                                child: null,
                            }, {
                                type: 'end'
                            }],
                        }, {
                            value: 'wb12',
                            label: '问题块b-问题1-答案2',
                            children: [{
                                type: 'daterange',
                                label: '问题块b2-问题1',
                                name: 'wb121',
                                ans: null,
                                child: null,
                            }],
                        }, {
                            value: 'wb13',
                            label: '问题块b-问题1-答案3',
                            children: [{
                                type: 'end'
                            }],
                        }]
                    }]
                }]
            }],

逻辑结构说明:

对象属性 描述
type 问题类型
label 页面展示文字
value 出现在select中,选项对应的值
name 之后ans对象中该答案所对应的键
ans 之后ans对象中该答案所对应的值
children 若选择该答案是所需要出现的问题块
child 该问题当前的子问题块

大概的逻辑思想就是这样了,在这之后还又一个单层级就可以实现该需求的逻辑方向,两个逻辑方向不同之处(所谓的多层级和单层级是指该逻辑结构是多维还是一维):

多层级 单层级
逻辑顺序可从结构中得到 逻辑顺序需要明确标示
只能拿到一个从叶子结点到根的问题线上的答案 多问题线也可获取
答案是从下往上获取 答案获取无逻辑

局部代码展示:

// index组件:



// level组件:


                    
                    

你可能感兴趣的:(前端,#,vue,#,组件)