关于前端:VuejsElementUIvant生成动态表单配置

7次阅读

共计 18517 个字符,预计需要花费 47 分钟才能阅读完成。

前言

我司最近在搭建一款后盾管理系统,应用的是 Vue 全家桶配合 Element-ui,遇到一个问题,须要解决很多的表单,所以想到的解决方案是通过后盾配置生成动静表单,这对于我来说也算是新的挑战,波及的性能有动静表单渲染和验证,那么一起来学习一下我是如何实现的吧!

本文仅仅代表笔者本人的思路,如果您有更好的实现形式,能够在下方留下您贵重的倡议。笔者将非常感激

开发筹备

须要储备的知识点

  • 理解 Element ui 表单
  • 理解 Vue 中的 $set(target,key,value) 办法
  • 理解 vant 中的表单组件

本我的项目是基于 vue-cli2.0 搭建的脚手架,在这里默认大家搭建好了, 谁赞成,谁拥护!

动态表单数据筹备

后盾返回的数据是这样的, 这里咱们拿一个 json 数据举例

{
    "showName": "姓名",    // 名称
    "showValue": null,    // 值
    "htmlElements": "输入框", // 表单类型
    "fieldLength": 99,    // 字段长度
    "requiredOrNot": 1,    //    是否必填
}

而后类型的话大略有以下几种

  • 输入框
  • 文本域
  • 日历控件
  • 下拉框
  • 单选框
  • 复选框

咱们为每一种类型生成一种组件,Test.vue 组件外面

data(){
    return{fieldArray:[],// 表单字段汇合
        fieldObj:{},
        sex:[{    // 性别
            name:'男',
            value:"male"
        },{
            name:"女",
            value:"female"
        }
            ],
        hobbies:[ // 喜好
            {
                name:"吃饭",
                value:"吃饭"
            },{
                name:"玩游戏",
                value:"玩游戏"
            },{
                name:"打豆豆",
                value:"打豆豆"
            },
        ],
        job:[{  // 职业
            name:"医生",
            value:"doctor"
        },{
            name:"老师",
            value:"teacher"
        },{
            name:"司机",
            value:"driver"
        }
            ]
    }
}

这里筹备多种日历控件是因为后续手机端应用 vant 组件的时候须要用到

因为 vue 中的数据是双向绑定的,所以只有在 data 外面的数据是能够实现双向绑定的,从新向 data 外面增加的数据无奈达到双向绑定的成果,官网为咱们提供了一个 set 办法。

作为靓仔的我,必定很贴心的为大家筹备了官网链接

官网链接

这里就不过多解说,官网比拟权威,本篇博客的重点是动静表单。

Vue.set(target,propertyName/index,value)

  • 参数

    • {Object | Array} target
    • {string | number} propertyName/index
    • {any} value
  • 返回值 :设置的值。

用法

向响应式对象中增加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上增加新 property,因为 Vue 无奈探测一般的新增 property (比方 this.myObject.newProperty = 'hi')

留神对象不能是 Vue 实例,或者 Vue 实例的根数据对象。

Element-ui 表单元素

官网链接

动静表单渲染

这里应用 axios 申请本地 json 数据,static/json/form.json

{
  "data":[
    {
      "showName": "姓名",
      "showValue": null,
      "htmlElements": "输入框",
      "fieldLength": 10,
      "requiredOrNot": 1,
      "desc":"请输出姓名"
    },
    {
      "showName": "形容",
      "showValue": null,
      "htmlElements": "文本域",
      "fieldLength": 99,
      "requiredOrNot": 1,
      "desc":"请输出形容"
    },
    {
      "showName": "喜好",
      "showValue": null,
      "htmlElements": "复选框",
      "requiredOrNot": 1,
      "desc":"请抉择喜好"
    },
    {
      "showName": "性别",
      "showValue": null,
      "htmlElements": "单选框",
      "requiredOrNot": 1
    },
    {
      "showName": "出生日期",
      "showValue": null,
      "htmlElements": "日历控件",
      "requiredOrNot": 1,
      "desc":"请抉择出生日期"
    },
    {
      "showName": "结婚工夫",
      "showValue": null,
      "htmlElements": "日历控件",
      "requiredOrNot": 1,
      "desc":"请抉择结婚工夫"
    },
    {
      "showName": "职业",
      "showValue": null,
      "htmlElements": "下拉框",
      "requiredOrNot": 1,
      "desc":"请抉择职业"
    }
  ]
}

Test.vue 文件

<template>
    <div>
        <h2> 测试动静表单 </h2>
      <el-form :model="fieldObj" ref="ruleForm" label-width="180px" class="demo-ruleForm">
        <template v-for="(item,index) of fieldArray">
          <template v-if="item.htmlElements===' 输入框 '">
            <el-form-item :label="item.showName">
              <el-input v-model="fieldObj[item.showName]" :max="item.fieldLength" :placeholder="item.desc" show-word-limit></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 文本域 '">
            <el-form-item :label="item.showName">
              <el-input type="textarea" rows="4" :placeholder="item.desc" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 日历控件 '">
            <el-form-item :prop="item.showName" :label="item.showName">
              <el-date-picker v-model="fieldObj[item.showName]" :name="item.showName" type="date"
                              format="yyyy-MM-dd" value-format="yyyy-MM-dd"
                              :placeholder="item.desc"
              ></el-date-picker>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 下拉框 '">
            <el-form-item  :label="item.showName">
              <el-select v-model="fieldObj[item.showName]" :placeholder="item.describe">
                <el-option
                  v-for="items in job"
                  :key="items.name"
                  :label="items.name"
                  :value="items.value">
                </el-option>
              </el-select>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 单选框 '">
            <el-form-item  :label="item.showName">
              <template v-for="(child,index) in sex">
                <el-radio v-model="fieldObj[item.showName]" :label="child.value">{{child.name}}</el-radio>
              </template>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 复选框 '">
            <el-form-item  :label="item.showName">
              <el-checkbox-group v-model="fieldObj[item.showName]">
                <template v-for="(child,index) of hobbies">
                  <el-checkbox :label="child.name"></el-checkbox>
                </template>
              </el-checkbox-group>
            </el-form-item>
          </template>
        </template>
      </el-form>
    </div>
</template>

<script>
  import axios from 'axios'
    export default {
        name: "Test",
      data(){
          return{fieldArray:[],// 表单字段汇合
            fieldObj:{},
            sex:[{    // 性别
                name:'男',
                value:"male"
              },{
                name:"女",
                value:"female"
            }
            ],
            hobbies:[ // 喜好
              {
                name:"吃饭",
                value:"吃饭"
              },{
                name:"玩游戏",
                value:"玩游戏"
              },{
                name:"打豆豆",
                value:"打豆豆"
              },
            ],
            job:[{  // 职业
                name:"医生",
                value:"doctor"
              },{
                name:"老师",
                value:"teacher"
              },{
                name:"司机",
                value:"driver"
            }
            ]
          }
      },
      mounted(){this.getFieldData();
      },
      methods:{getFieldData(){ // 获取动静表单数据
            axios.get("../static/json/form.json").then(data=>{
              let response=data.data.data;
              this.fieldArray=response;
              for(let i=0;i<response.length;i++){let item=response[i];
                if(item.htmlElements==='复选框'){this.$set(this.fieldObj,item.showName,[]);
                }else {this.$set(this.fieldObj,item.showName,item.showValue);
                }
              }
            })
          }
      }
    }
</script>

<style scoped>

</style>

当初的话,表单曾经全副渲染结束了,也实现了双向绑定,当初须要做的是如何实现动静表单验证。

官网解释:Form 组件提供了表单验证的性能,只须要通过 rules 属性传入约定的验证规定,并将 Form-Item 的 prop 属性设置为需校验的字段名即可,

  • prop 字段
  • rules
  • model

在这里 rules 设置为动静的,而不是放在 data 外面提前写好,这里须要晓得每一种类型的触发模式

  • 输入框 / 文本域 trigger: ‘blur’
  • 单选框 / 复选框 / 日历控件 / 下拉框 trigger: ‘change’

动静表单验证

对于表单中的每一种验证模式都理解之后,Test.vue 外面的文件就变成了

<template>
    <div>
        <h2> 测试动静表单 </h2>
      <el-form :model="fieldObj" ref="ruleForm" label-width="180px" class="demo-ruleForm">
        <template v-for="(item,index) of fieldArray">
          <template v-if="item.htmlElements===' 输入框 '">
            <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{required: true, message:' 请输出 '+item.showName, trigger:'blur'}]:[]">
              <el-input v-model="fieldObj[item.showName]" :max="item.fieldLength"
                        :placeholder="item.desc" show-word-limit ></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 文本域 '">
            <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{required: true, message:' 请输出 '+item.showName, trigger:'blur'}]:[]">
              <el-input type="textarea" rows="4" :placeholder="item.desc" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 日历控件 '">
            <el-form-item :prop="item.showName" :label="item.showName" :rules="item.requiredOrNot==1?[{required: true, message:' 请抉择 '+item.showName, trigger:'change'}]:[]">
              <el-date-picker v-model="fieldObj[item.showName]" :name="item.showName" type="date"
                              format="yyyy-MM-dd" value-format="yyyy-MM-dd"
                              :placeholder="item.desc"
              ></el-date-picker>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 下拉框 '">
            <el-form-item  :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{required: true, message:' 请抉择 '+item.showName, trigger:'change'}]:[]">
              <el-select v-model="fieldObj[item.showName]" :placeholder="item.describe">
                <el-option
                  v-for="items in job"
                  :key="items.name"
                  :label="items.name"
                  :value="items.value">
                </el-option>
              </el-select>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 单选框 '">
            <el-form-item  :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{required: true, message:' 请抉择 '+item.showName, trigger:'change'}]:[]">
              <template v-for="(child,index) in sex">
                <el-radio v-model="fieldObj[item.showName]" :label="child.value">{{child.name}}</el-radio>
              </template>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements===' 复选框 '">
            <el-form-item  :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{required: true, message:' 请抉择 '+item.showName, trigger:'change'}]:[]">
              <el-checkbox-group v-model="fieldObj[item.showName]">
                <template v-for="(child,index) of hobbies">
                  <el-checkbox :label="child.name"></el-checkbox>
                </template>
              </el-checkbox-group>
            </el-form-item>
          </template>
        </template>
        <div class="text-align">
          <el-button type="primary" @click="submitForm('ruleForm')"> 立刻创立 </el-button>
          <el-button @click="resetForm('ruleForm')"> 重置 </el-button>
        </div>
      </el-form>
    </div>
</template>

<script>
  import axios from 'axios'
    export default {
        name: "Test",
      data(){
          return{fieldArray:[],// 表单字段汇合
            fieldObj:{},
            sex:[{    // 性别
                name:'男',
                value:"male"
              },{
                name:"女",
                value:"female"
            }
            ],
            hobbies:[ // 喜好
              {
                name:"吃饭",
                value:"吃饭"
              },{
                name:"玩游戏",
                value:"玩游戏"
              },{
                name:"打豆豆",
                value:"打豆豆"
              },
            ],
            job:[{  // 职业
                name:"医生",
                value:"doctor"
              },{
                name:"老师",
                value:"teacher"
              },{
                name:"司机",
                value:"driver"
            }
            ]
          }
      },
      mounted(){this.getFieldData();
      },
      methods:{getFieldData(){ // 获取动静表单数据
            axios.get("../static/json/form.json").then(data=>{
              let response=data.data.data;
              this.fieldArray=response;
              for(let i=0;i<response.length;i++){let item=response[i];
                if(item.htmlElements==='复选框'){this.$set(this.fieldObj,item.showName,[]);
                }else {this.$set(this.fieldObj,item.showName,item.showValue);
                }
              }
            })
          },
        submitForm(formName){ // 提交验证
          this.$refs[formName].validate((valid) => {if (valid) {console.log('提交数据');
            } else {return false;}
          });
        },
        resetForm(formName) { // 重置表单
          this.$refs[formName].resetFields();}
      }
    }
</script>

<style scoped>

</style>

新增的内容有:

  • el-form-item 新增了:prop=”item.showName”
  • el-form-item 新增了:rules=”item.requiredOrNot==1?[{required: true, message: ‘ 请抉择 ’+item.showName, trigger: ‘change’}]:[]”
  • el-form-item 新增了:rules=”item.requiredOrNot==1?[{required: true, message: ‘ 请输出 ’+item.showName, trigger: ‘blur’}]:[]”
  • methods 外面新增了验证办法和重置表单的办法

vant 动静表单验证

因为 pc 端和手机端是配套应用的,所以手机端咱们也实现动静表单的性能,

废话不多说上号!

还是拿 Test.vue 组件来举例子,对于挪动端的话,首先须要装置 vant 依赖,默认大家曾经装置好了。

vant 官网

动静表单渲染

因为手机端没有下拉框这个组件,而是应用 Picker 选择器来代替,那么就须要思考一个问题, 多个 picker 的话怎么实现一一对应呢? 该怎么解决?

form.json 外面新增一个对象 - 城市, 之前的代码还是能够复用

{
    "showName": "城市",
    "showValue": null,
    "htmlElements": "下拉框",
    "requiredOrNot": 1,
    "desc":"请抉择职业"
}

这样一来就有多个下拉框,从而来解决多个 picker 的问题。

Test.vue 的代码

html 代码区

<template>
    <div>
      <h2 class="title"> 测试 vant 动静表单 </h2>
      <van-form @submit="submitClaim">
        <template v-for="(item,index) of fieldArray">
          <template v-if="item.htmlElements===' 输入框 '">
            <van-field :maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"/>
          </template>
          <template v-if="item.htmlElements===' 文本域 '">
            <van-field rows="2"  autosize :label="item.showName" :name="item.showName" type="textarea"  v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit/>
          </template>
          <template v-if="item.htmlElements===' 日历控件 '">
            <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" />
          </template>
          <template v-if="item.htmlElements===' 复选框 '">
            <van-field :name="item.showName" :label="item.showName">
              <template #input>
                <van-checkbox-group v-model="fieldObj[item.showName]" direction="horizontal">
                  <template v-for="(child,index) of hobbies">
                    <van-checkbox :name="child.value">{{child.name}}</van-checkbox>
                  </template>
                </van-checkbox-group>
              </template>
            </van-field>
          </template>
          <template v-if="item.htmlElements===' 单选框 '">
            <van-field :name="item.showName" :label="item.showName">
              <template #input>
                <van-radio-group v-model="fieldObj[item.showName]" direction="horizontal">
                  <template v-for="(child,index) of sex">
                    <van-radio :name="child.value">{{child.name}}</van-radio>
                  </template>
                </van-radio-group>
              </template>
            </van-field>
          </template>
          <template v-if="item.htmlElements===' 下拉框 '">
            <van-field :name="item.showName" is-link :label="item.showName"  :readonly="true" v-model="fieldObj[item.showName]"/>
          </template>
        </template>
      </van-form>
    </div>
</template>

JavaScript 代码区

  import axios from 'axios'
    export default {
        name: "Test",
      data(){
          return{fieldArray:[],// 表单字段汇合
            fieldObj:{},
            sex:[{    // 性别
              name:'男',
              value:"male"
            },{
              name:"女",
              value:"female"
            }
            ],
            hobbies:[ // 喜好
              {
                name:"吃饭",
                value:"吃饭"
              },{
                name:"玩游戏",
                value:"玩游戏"
              },{
                name:"打豆豆",
                value:"打豆豆"
              },
            ],
          }
      },
      mounted(){this.getFieldArray();
      },
      methods:{getFieldArray(){  // 获取本地动静表单配置 json 数据
             axios.get("../../static/json/form.json").then(data=>{
               let response=data.data.data;
               this.fieldArray=response;
               for(let i=0;i<response.length;i++){let item=response[i];
                 if(item.htmlElements==='复选框'){this.$set(this.fieldObj,item.showName,[]);
                 }else {this.$set(this.fieldObj,item.showName,item.showValue);
                 }
               }
             })
          },
        submitClaim(taskInfo){}}
    }

当初的话根本实现了输入框,文本域,单选框,复选框的值双向绑定,下一步是解决多个日历框和下拉框的取值一一对应。

日历框和弹出层都是通过 v -model 来管制显示和暗藏,所以只需晓得日历框和弹出层的个数,而后循环遍历解决就能够了,getFieldArray 办法重新处理

axios.get("../../static/json/form.json").then(data=>{
    let response=data.data.data;
    this.fieldArray=response;
    for(let i=0;i<response.length;i++){let item=response[i];
        if(item.htmlElements==='复选框'){this.$set(this.fieldObj,item.showName,[]);
        }else if(item.htmlElements==='日历控件'){this.$set(this.dateObj,item.showName,false); // 日历控件全副先暗藏
            this.$set(this.fieldObj,item.showName,item.showValue);
        }else if(item.htmlElements=='下拉框'){this.$set(this.fieldObj,item.showName,item.showValue);
            this.$set(this.dropDownObj,item.showName,false); // 弹出层全副先暗藏
        }else {this.$set(this.fieldObj,item.showName,item.showValue);
        }
    }
})

data 数据外面新增 dateObj 对象

dateObj:{},// 管制日期的显示暗藏 
解决日历控件

页面 html 新增相干内容

 <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dateObj[item.showName]=true"/>
<template v-for="(item,key,index) of dateObj">
   <van-calendar v-model="dateObj[key]" @confirm="(date)=>onConfirmTime(date,item,key)"/>
 </template>

methods 新增办法

onConfirmTime(date,item,key){ // 日历控件
    this.fieldObj[key]=this.formatDate(date);
    this.dateObj[key]=false;
},
formatDate(date) {  // 格式化日期
    let year=date.getFullYear();
    let month=date.getMonth()+1;
    let day=date.getDate();
    if(month<10){month='0'+month;}
    if(day<10){day='0'+day;}
    return `${year}-${month}-${day}`;
},

应用 v -model 绑定提前写好的日期对象 dateObj,而后遍历对象来管制每一个日历控件的显示暗藏。

绑定对应的 key 值,这样就能够达到获取每一个日历对象点击之后对应的值。

解决下拉框

data 外面新增 dropDownObj 对象,dropDownTempObj 对象,dropDownMap map 对象

dropDownObj:{},// 管制下拉框的显示暗藏
dropDownTempObj:{},// 下拉框对象,用于 picker 外面的值
dropDownMap:new Map(),

mounted 生命周期外面新增

this.dropDownMap.set("职业",["医生","老师","司机"]);
this.dropDownMap.set("城市",["北京","上海","广州","深圳"])

页面新增 html 内容

<van-field :name="item.showName" is-link :label="item.showName"  :readonly="true" v-model="fieldObj[item.showName]" @click="dropDownObj[item.showName]=true"/>
<template v-for="(item,key,index) of dropDownObj">
    <van-popup v-model="dropDownObj[key]" position="bottom" :style="{width:'100%'}">
        <van-picker show-toolbar  @confirm="(value)=>onConfirmDropdown(value,key)" @cancel="dropDownObj[key]=false" :columns="handleData(dropDownTempObj[key])"/>
    </van-popup>
</template>

methods 新增相干办法

onConfirmDropdown(value,key){  // 下拉框选中数据
  this.dropDownObj[key]=false;
  this.fieldObj[key]=value;
},
handleData(key){ // 下拉框获取每一个配置项
  return this.dropDownMap.get(key);
},

getFieldArray 办法重写

axios.get("../../static/json/form.json").then(data=>{
    let response=data.data.data;
    this.fieldArray=response;
    for(let i=0;i<response.length;i++){let item=response[i];
        if(item.htmlElements==='复选框'){this.$set(this.fieldObj,item.showName,[]);
        }else if(item.htmlElements==='日历控件'){this.$set(this.dateObj,item.showName,false); // 日历控件全副先暗藏
            this.$set(this.fieldObj,item.showName,item.showValue);
        }else if(item.htmlElements=='下拉框'){this.$set(this.fieldObj,item.showName,item.showValue);
            this.$set(this.dropDownObj,item.showName,false); // 弹出层全副先暗藏
            this.$set(this.dropDownTempObj,item.showName,item.showName);
        }else {this.$set(this.fieldObj,item.showName,item.showValue);
        }
    }
})

最终实现成果

能够看到最终所有的数据都实现了双向绑定,提交到后盾的数据就是表单外面的数据,也能够全副获取到,最初须要实现的就是表单的验证的性能。

动静表单验证

对于输入框和文本域的验证比较简单,只须要增加 required 和 rules 验证规定就能够

输入框和文本域

<van-field
 :required="item.requiredOrNot==1?true:false":maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"  :rules="[{required: true, message:' 请填写 '+item.showName}]"/>

这样一来就根本实现了输入框和文本域的验证,至于其它的 form 表单类型的验证笔者还在钻研当中

vant 动静表单解决全副代码

html 代码片段

<van-form @submit="submitClaim">
    <template v-for="(item,index) of fieldArray">
        <template v-if="item.htmlElements===' 输入框 '">
            <van-field :maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"/>
        </template>
        <template v-if="item.htmlElements===' 文本域 '">
            <van-field rows="2"  autosize :label="item.showName" :name="item.showName" type="textarea"  v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit/>
        </template>
        <template v-if="item.htmlElements===' 日历控件 '">
            <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dateObj[item.showName]=true"/>
        </template>
        <template v-if="item.htmlElements===' 复选框 '">
            <van-field :name="item.showName" :label="item.showName">
                <template #input>
                    <van-checkbox-group v-model="fieldObj[item.showName]" direction="horizontal">
                        <template v-for="(child,index) of hobbies">
                            <van-checkbox :name="child.value">{{child.name}}</van-checkbox>
                        </template>
                    </van-checkbox-group>
                </template>
            </van-field>
        </template>
        <template v-if="item.htmlElements===' 单选框 '">
            <van-field :name="item.showName" :label="item.showName">
                <template #input>
                    <van-radio-group v-model="fieldObj[item.showName]" direction="horizontal">
                        <template v-for="(child,index) of sex">
                            <van-radio :name="child.value">{{child.name}}</van-radio>
                        </template>
                    </van-radio-group>
                </template>
            </van-field>
        </template>
        <template v-if="item.htmlElements===' 下拉框 '">
            <van-field :name="item.showName" is-link :label="item.showName"  :readonly="true" v-model="fieldObj[item.showName]" @click="dropDownObj[item.showName]=true"/>
        </template>
    </template>
    <van-button  type="info" round  native-type="submit" :style="{width:'100%',marginTop:'15px'}"> 提交 </van-button>
</van-form>
<template v-for="(item,key,index) of dateObj">
    <van-calendar v-model="dateObj[key]" @confirm="(date)=>onConfirmTime(date,item,key)"/>
</template>
<template v-for="(item,key,index) of dropDownObj">
    <van-popup v-model="dropDownObj[key]" position="bottom" :style="{width:'100%'}">
        <van-picker show-toolbar  @confirm="(value)=>onConfirmDropdown(value,key)" @cancel="dropDownObj[key]=false" :columns="handleData(dropDownTempObj[key])"/>
    </van-popup>
</template>

JavaScript 代码片段

import axios from 'axios'
export default {
    name: "Test",
    data(){
        return{fieldArray:[],// 表单字段汇合
            fieldObj:{},
            sex:[{    // 性别
                name:'男',
                value:"male"
            },{
                name:"女",
                value:"female"
            }
                ],
            hobbies:[ // 喜好
                {
                    name:"吃饭",
                    value:"吃饭"
                },{
                    name:"玩游戏",
                    value:"玩游戏"
                },{
                    name:"打豆豆",
                    value:"打豆豆"
                },
            ],
            dateObj:{// 管制日期的显示暗藏},
            dropDownObj:{// 管制下拉框的显示暗藏},
            dropDownTempObj:{// 下拉框对象,用于 picker 外面的值},
            dropDownMap:new Map(),}
    },
    mounted(){this.getFieldArray();
        this.dropDownMap.set("职业",["医生","老师","司机"]);
        this.dropDownMap.set("城市",["北京","上海","广州","深圳"])
    },
    methods:{getFieldArray(){  // 获取本地动静表单配置 json 数据
            axios.get("../../static/json/form.json").then(data=>{
                let response=data.data.data;
                this.fieldArray=response;
                for(let i=0;i<response.length;i++){let item=response[i];
                    if(item.htmlElements==='复选框'){this.$set(this.fieldObj,item.showName,[]);
                    }else if(item.htmlElements==='日历控件'){this.$set(this.dateObj,item.showName,false); // 日历控件全副先暗藏
                        this.$set(this.fieldObj,item.showName,item.showValue);
                    }else if(item.htmlElements=='下拉框'){this.$set(this.fieldObj,item.showName,item.showValue);
                        this.$set(this.dropDownObj,item.showName,false); // 弹出层全副先暗藏
                        this.$set(this.dropDownTempObj,item.showName,item.showName);
                    }else {this.$set(this.fieldObj,item.showName,item.showValue);
                    }
                }
            })
        },
        onConfirmTime(date,item,key){ // 日历控件
            this.fieldObj[key]=this.formatDate(date);
            this.dateObj[key]=false;
        },
        onConfirmDropdown(value,key){  // 下拉框选中数据
            this.dropDownObj[key]=false;
            this.fieldObj[key]=value;
        },
        handleData(key){ // 下拉框获取每一个配置项
            return this.dropDownMap.get(key);
        },
        formatDate(date) {  // 格式化日期
            let year=date.getFullYear();
            let month=date.getMonth()+1;
            let day=date.getDate();
            if(month<10){month='0'+month;}
            if(day<10){day='0'+day;}
            return `${year}-${month}-${day}`;
        },
        submitClaim(taskInfo){console.log(taskInfo);
        }
    }
}

总结

整体来说动静表单的解决综合难度不算很大,须要的是如何对数据进行解决,当然还有不足之处是没有做到对文件上传的解决,代码的优化水平没有做好,v-for 外面写了很多 v -if, 是否能够应用独自的组件进行解决,这些都是有待须要思考的问题。

结尾

如果感觉本篇博客对您有帮忙的话,记得给作者三连,点赞👍👍👍,关注,珍藏,您的反对就是我写作路上最大的能源,咱们下篇文章见。

正文完
 0