使用Vue生成动态表单


Posted in Javascript onNovember 26, 2019

开需求会了,产品说这次需求的表单比较多,目前有18个,后期的表单可能会有增加、修改。我作为这次的前端开发,看到这样的需求,心里知道要这样搞不得把自己累死,首先表单居多,还会有变更,以后维护起来也让人心力憔悴。

于是我提议做动态表单,做一个表单的配置系统,在系统里配置表单类型、表单得字段、以及对表单得管理。后来重新评审了需求,系统部分由后端自行开发,我要处理的部分是动态生成表单,展现提交的表单,以及对表单的处理情况。

数据接口设计

表单类型的接口就不用说了,这个比较简单。我跟后端约定了一个预备创建工单接口,这个接口是后端告知前端,需要生成一个什么样的表单。

预备创建表单接口(其中字段解释说明):

id
name
type
title
prompt_msg
selectObj

{
 "code": 0,
 "msg": "success",
 "data": {
 "list": [{
  "id": 10,
  "name": "check_type",
  "type": "select_item",
  "title": "审核类型",
  "prompt_msg": "请填写审核类型",
  "selectObj": [{
  "id": 1,
  "item": "预审核"
  }, {
  "id": 2,
  "item": "患者审核"
  }],
  "val": null,
  "rank": 0
 }, {
  "id": 16,
  "name": "bank_branch_info",
  "type": "string",
  "title": "支行信息",
  "prompt_msg": "请填写支行信息",
  "selectObj": null,
  "val": null,
  "rank": 0
 }, {
  "id": 19,
  "name": "project_content",
  "type": "multiple",
  "title": "项目内容",
  "prompt_msg": "请填写项目内容",
  "selectObj": null,
  "val": null,
  "rank": 0
 }, {
  "id": 22,
  "name": "project_extension_time",
  "type": "integer",
  "title": "项目延长时间",
  "prompt_msg": "请填写项目延长时间",
  "selectObj": null,
  "val": null,
  "rank": 0
 }, {
  "id": 24,
  "name": "images",
  "type": "images",
  "title": "图片",
  "prompt_msg": "请上传图片",
  "selectObj": null,
  "val": null,
  "rank": 0
 }]
 }
}

通过Vue动态组件渲染表单

现在预备创建表单接口文档都了,该怎么渲染动态表单呢?动态表单的元素类型有5类,按照这个类别创建五个元素组件。

1. 上传图片组件

上传图片组件这里使用了 Uploader 组件。

<template>
  <div class="default images">
    <div class="lable">{{ item.title }}</div>
    <div v-if="item.val === null" class="content">
      <Uploader 
        :max-num="8"
        :user-imgs="project_image"
        @change="onUploadProject"
      />
    </div>
    <div v-else class="img-wrap">
      <img v-for="(it, idx) in item.val" :src="it" :key="idx" @click="preview(idx, item.val)">
    </div>
  </div>
</template>

2. 多行输入框组件

默认多行输入框为3行

<template>
  <div v-if="item" class="default multiple">
    <div class="lable">{{ item.title }}</div>
    <template>
      <textarea
        rows="3" 
        :placeholder="item.prompt_msg" 
        v-model="value" 
        :value="it.item">
    </template>
  </div>
</template>

3. 下拉选择框组件

使用了element-ui的 el-select

<template>
  <div v-if="item" class="default select_item">
    <div class="lable select-lable">{{ item.title }}</div>
    <div class="content">
      <el-select
        v-model="value" 
        placeholder="请选择类型" 
        class="el-select-wrap" 
        size="mini"
        @change="onChangeFirstValue"
      >
        <el-option
          v-for="it in item.selectObj"
          :key="it.id"
          :label="it.item"
          :value="it.item">
        </el-option>
      </el-select>
    </div>
  </div>
</template>

其它两个数字单行输入框组件、文本单输入框组件跟多行输入框组件类似。

组件都创建好了,为了方便统一管理这些自定义组件。将组件们引入再导出,通过export default复合的形式。

// 单行文本输入框组件
export { default as String } from './string.vue' 
// 单行数字输入框组件
export { default as Integer } from './integer.vue' 
// 多行文本输入框组件
export { default as Multiple } from './multiple.vue' 
// 下拉列表选择器组件
export { default as Select_item } from './select_item.vue' 
// 上传图片组件
export { default as Images } from './images.vue'

再动态表单页面统一引入,以Vue动态组件的形式进行渲染, is 属性为动态组件名。

<template>
  <div class="g-container">
    <component 
      v-for="(item, number) in freedomConfig" 
      :key="item.name"
      :is="item.type" 
      :item="item" 
      :number="number" 
      @changeComponent="changeComponentHandle"
    ></component>
  </div>
</template>

<script>
  import * as itemElements from '../../components/itemElement'
  
  export default {
    components: itemElements,
  }
</script>

上面完成后,动态表单展现出来了。表单是动态生成的,如何进行表单验证,和表单数据的汇总呢?

表单数据汇总

再动态渲染组件的,传入了 number 参数,这个参数用来标识当前组件位于动态表单的第几个,方便后期填入数据后,进行数据保存。

默认value属性值为空,对value进行监听,当value变动的时 候进行emit,告诉父组件数据变更了,请保存。

data() {
  return {
    value: ''
  }
},
watch: {
  value(v, o) {
    this.throttleHandle(() => {
      this.$emit('changeComponent', {
        number: this.number,
        value: this.$data.value
      })
    })
  }
},

但是数据保存到哪里?怎么保存呢? 让后端给一个表单全部字段的接口,取到数据存到data中,每次数据更新就去查找是否存在这个字段,有的话就赋值保存起来。后面提交的时候,就提交这个对象。

表单校验

提交的时候,希望用户能够把表单填完再调用提交接口,需要前端校验是否填完没有的话,就给响应的toast请提示,阻止表单提交。

this.checkFrom(freedomConfig, preWordorderData).then(canSubmit => {
  canSubmit && postSubmitWorkorder(preWordorderData).then(res => {
    if (res.code === 0) {
      showLoading()
      this.$router.push(`/detail/${res.data.id}`)
    }
  })
})

checkFrom 为我们的校验方法,循环遍历预创建表单,从data里查看该字段是否有值,没有的话就给于toast提示。并返回一个promise, resolve(false) 。如果都校验通过返回 resolve(true) 。这样就可以使checkFrom成为一个异步函数。

其中需要注意的是下拉框选择后的值为大于0的数字、上传图片的属性值是数组。

一个动态表单的创建、校验、数据整合就完成了。很多时候需要写大量代码的场景思路上很简单,反倒是抽象一个组件需要考虑的更多。

总结

以上所述是小编给大家介绍的使用Vue生成动态表单,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
用javascript模仿ie的自动完成类似自动完成功的表单
Dec 12 Javascript
jQuery插件实现表格隔行换色且感应鼠标高亮行变色
Sep 22 Javascript
onkeyup,onkeydown和onkeypress的区别介绍
Oct 21 Javascript
根据身份证号自动输出相关信息(籍贯,出身日期,性别)
Nov 15 Javascript
javascript 循环调用示例介绍
Nov 20 Javascript
JS实现根据出生年月计算年龄
Jan 10 Javascript
BootStrap的JS插件之轮播效果案例详解
May 16 Javascript
JavaScript来实现打开链接页面的简单实例
Jun 02 Javascript
vue全局使用axios的方法实例详解
Nov 22 Javascript
layui前端时间戳转化实例
Nov 15 Javascript
解决Vue.js应用回退或刷新界面时提示用户保存修改问题
Nov 24 Javascript
JS画布动态实现黑客帝国背景效果
Nov 08 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
Nov 26 #Javascript
Vue+ElementUI使用vue-pdf实现预览功能
Nov 26 #Javascript
详解小程序如何动态绑定点击的执行方法
Nov 26 #Javascript
vue element-ui读取pdf文件的方法
Nov 26 #Javascript
Vue+Element-UI实现上传图片并压缩
Nov 26 #Javascript
jQuery实现轮播图效果
Nov 26 #jQuery
JavaScript使用百度ECharts插件绘制饼图操作示例
Nov 26 #Javascript
You might like
德生S2000电路分析
2021/03/02 无线电
JoshChen_php新手进阶高手不可或缺的规范介绍
2013/08/16 PHP
php使用iconv中文截断问题的解决方法
2015/02/11 PHP
7个鲜为人知却非常实用的PHP函数
2015/07/01 PHP
tp5.1 框架数据库常见操作详解【添加、删除、更新、查询】
2020/05/26 PHP
经常用到的JavasScript事件的翻译
2007/04/09 Javascript
javascript中callee与caller的区别分析
2015/04/20 Javascript
javascript中$(function() {});写与不写有哪些区别
2015/08/10 Javascript
jquery捕捉回车键及获取checkbox值与异步请求的方法
2015/12/24 Javascript
AngularJS执行流程详解
2017/02/17 Javascript
Bootstrap的popover(弹出框)在append后弹不出(失效)
2017/02/27 Javascript
vue中锚点的三种方法
2018/07/06 Javascript
RxJS在TypeScript中的简单使用详解
2020/04/13 Javascript
vue tab切换,解决echartst图表宽度只有100px的问题
2020/07/19 Javascript
使用js原生实现年份轮播选择效果实例
2021/01/12 Javascript
[02:02]DOTA2英雄基础教程 斯拉达
2013/12/11 DOTA
[11:57]《一刀刀一天》第十七期:TI中国军团加油!
2014/05/26 DOTA
[03:30]完美盛典趣味短片 CSGO2019年度名场面
2019/12/07 DOTA
python开发之str.format()用法实例分析
2016/02/22 Python
python面向对象实现名片管理系统文件版
2019/04/26 Python
python+rsync精确同步指定格式文件
2019/08/29 Python
python导入不同目录下的自定义模块过程解析
2019/11/18 Python
python实现ftp文件传输功能
2020/03/20 Python
Python 如何展开嵌套的序列
2020/08/01 Python
Python中三维坐标空间绘制的实现
2020/09/22 Python
使用postMessage让 iframe自适应高度的方法示例
2019/10/08 HTML / CSS
奥地利网上现代灯具和灯饰店:Lampenwelt.at
2018/01/29 全球购物
C/C++程序员常见面试题二
2015/11/19 面试题
Shell编程面试题
2012/05/30 面试题
中国梦演讲稿3分钟
2014/08/19 职场文书
关于清明节的演讲稿
2014/09/13 职场文书
2015年国庆节活动总结
2015/03/23 职场文书
大学开学感言
2015/08/01 职场文书
销区经理年终述职报告模板
2019/11/28 职场文书
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android
mysql的单列多值存储实例详解
2022/04/05 MySQL