vue2 中如何实现动态表单增删改查实例


Posted in Javascript onJune 09, 2017

最近项目中遇到的需求是要操作大量的表单,之前的项目中有做过这方的研究,只不过是用jquery来操作。

项目A

先简单说说以前项目A中的应用场景,可能有小伙伴儿也遇到相同的需求。A项目是公司的OA系统中有的项目,是用java的jsp渲染的页面,需求是要改成:嵌入APP中显示,前后端分离, 后端返回的内容,还不能修改, 只是后端同事做了下接口处理,返回给前端的是一大堆的表单数据。

每个表单都有多个字段表示它的属性:

  1. 是否可编辑
  2. 表单类型 (text, textarea, select, radio, checkbox, hidden等 )
  3. 与之联动的其他表单
  4. 。。。之前的方案就是各个表单类型和字段属性进行判断,调用不同的UI组件(如时间日历选择器等)

项目B

现在遇到的项目,展示类型少很多,第一个想到的就是同样的方法,不过这次使用的是Vue的双向绑定。

以下是我在python后端项目中的经验,如果没有兴趣可以直接看最后的动态表单部分

1 python 后端项目中如何引入Vue

项目B用的是python的jinjia2的模板, 同样都是 {{}} 去解析数据,这种情况下怎么办呢?

{% raw %}
<script type="text/x-template" id="dialog-wrap">
<div class="ms-dialog-wrap" v-show="visible">
 <div class="ms-dialog-inner">
  <div class="ms-dialog-title">{{title}}</div>
  <div class="ms-dialog-body">
   <div class="ms-dialog-content">
    <slot></slot>
   </div>
   <div class="ms-dialog-actions">
    <a class="ms-button" @click="cancelAction">取消</a>
    <a class="ms-button ms-success" @click="confirmSuccess">确定</a>
   </div>
  </div>
 </div>
 <div class="ms-overlayer" @click="cancelAction"></div>
</div>
</script>
{% endraw %}

jinjia2中使用 raw 可以阻止解析内部的代码,这样就可以引入我们的vue模板了,这里是我写的一个dialog弹框的组件

2 定义组件

这里以dialog弹窗组件为例子,直接上代码

// dialog弹框
Vue.component('ms-dialog', {
 name: 'ms-dialog',
 template: '#dialog-wrap',
 data: function () {
  return {
  }
 },
 props: {
  title: String,
  value: {
   type: Boolean,
   required: false
  }
 },
 computed: {
  visible: function () {
   return this.value
  }
 },
 watch: {
  visible: function (newVal) {
   if (newVal) {
    document.addEventListener('wheel', this.disabledScroll, false)
   } else {
    document.removeEventListener('wheel', this.disabledScroll, false)
   }
  }
 },
 methods: {
  confirmSuccess: function () {
   this.$emit('confirm-success')
  },
  cancelAction: function () {
   this.$emit('input', false)
  },
  disabledScroll: function (e) {
   e.preventDefault()
  }
 },
 beforeDestroy: function () {
  document.removeEventListener('scroll', this.disabledScroll, false)
 }
})

动态表单组件

一般的需求是:

  1. 一个列表,可以实现列表的动态添加,删除。
  2. 列表中的每一项是动态的表单,表单个数不确定,
  3. 有提交功能,提交或者可以保存整个表单
  4. 保存的表单,通过接口调回后,回填表单,还可以再次修改、增加、删除等

1 如何生成动态表单

<template v-for="item in lists">
   <div class="list-item" v-if="list.type === 'input'">
    <label>用户名</label>
    <input type="text" v-model="item.value" :value="list.defaultValue" class="form-control">
   </div>
   <div class="list-item" v-if="list.type === 'input'">
    <label>密码</label>
    <input type="text" v-model="item.value" :value="list.defaultValue" class="form-control">
   </div>
   <div class="list-item" v-if="list.type === 'textarea'">
    <label>说明</label>
    <textarea rows="3" v-model="item.value" :value="list.defaultValue" class="form-control"></textarea>
   </div>
   <div class="list-item" v-if="list.type === 'select'">
    <label>性别</label>
    <select v-model="list.value" :value="list.defaultValue">
      <option v-for="sub in list.source" :value="sub.value">{{sub.label}}</option>
    </select>
   </div>
</template>

我们的与后端商量好的数据格式可以是这样的;

lists: [{
 type: 'input',
 defaultValue: 'tom',
 value: 'tom'
}, {
 type: 'input',
 defaultValue: '123456',
 value: '123456'
}, {
 type: 'textarea',
 defaultValue: '123456',
 value: '123456'
}, {
 type: 'select',
 defaultValue: '0',
 value: '0',
 source: [{
  value: '1',
  label: '男'
 }, {
  value: '1,
  label: '女'
 }]
}]

这样一个动态模板就生成了,其他更多类型都可以定义。这份模板数据,一般是需要缓存的。因为接下来的 添加操作也需要这份数据。

添加操作

上面的template只是其中一个动态列表。

<div v-for="book in books">
  <template v-for="item in book.lists">
   ......
  </template>
</div>
<div class="actions">
<button @click="add"></button>
</div>

add的方法一般是:

methods: {
 add: function () {
  this.books.push({
  lists: [{
   type: 'input',
   defaultValue: 'tom',
   value: 'tom'
  }, {
   type: 'input',
   defaultValue: '123456',
   value: '123456'
  }, {
   type: 'textarea',
   defaultValue: '123456',
   value: '123456'
  }, {
   type: 'select',
   defaultValue: '0',
   value: '0',
   source: [{
    value: '1',
    label: '男'
   }, {
    value: '1,
    label: '女'
   }]
  }]
 })
 },

这里需要注意的是,如果这份模板的数据,你是通过在data属性中定义的字段去缓存的,那有可能遇到的是你通过添加操作之后的表单的值会,会随着其中的某个表单的值一起联动。

具体原因,猜测是这里的数据已经是变成响应式的了, 又或者你 通过实例化后的值去缓存这份模板数据,可能结果还是这样。
具体代码可能是这样的:

var vm = new Vue({
  data: {
    books: [],
    cacheTemplate: null
  },
  methods: {
    getForms: function (argument) {
      this.$http.post(url, paras).then(res => {
        // 此处缓存了这份模板数据,cacheTemplate中的数据已经变成响应式的了
        this.cacheTemplate = res.body.data
        this.books.push(res.body.data) // 创建第一动态表单列表

        // 或者你是这是定义的的, 此时data中没有cacheTemplate这个值, 
        // 这样定义按理说是非响应式的,但实际情况并非如此,在项目中发现它还是会影响其他表单
        vm.cacheTemplate = res.body.data
        this.books.push(res.body.data) // 创建第一动态表单列表
      }, res => {

      })
    },
    add: function () {
      // 此处你会发现你新创建的表单的值会影响其他表单
      // log出来this.cacheTemplate你会发现里面的值已经发生了变换
      this.books.push(this.cacheTemplate)
    }
  }
})

这里this.cacheTemplate的值为什么会发生变换,没有搞明白, 猜测原因可能是变成响应式了,vue中会实时监控跟踪,对vue原理理解好的小伙伴可以评论告诉我原因。

下面说下我的解决方法: 我不管你是不是响应式的,因为是对象,你才能监控到变换,那我把你变成字符串不就好了。
直接上代码:

var vm = new Vue({
  data: {
    books: [],
    cacheTemplate: null
  },
  methods: {
    getForms: function (argument) {
      this.$http.post(url, paras).then(res => {
        // 此处同样缓存了这份模板数据,不同的是把它变成了字符串
        this.cacheTemplate = JOSN.stringify(res.body)
        this.books.push(res.body) // 创建第一动态表单列表
      }, res => {

      })
    },
    add: function () {
      // 此处转化成json对象,你发现this.cacheTemplate中的值是没有变换的。
      var cacheTemplate = JSON.parse(this.cacheTemplate)
      this.books.push(cacheTemplate)
    }
  }
})

这样其他表单值变换的时候都不会影响到我这份模板的数据,问题解决了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript获取form里的表单元素的示例代码
Feb 14 Javascript
jquery插件jquery.dragscale.js实现拖拽改变元素大小的方法(附demo源码下载)
Feb 25 Javascript
Node.js+Express配置入门教程
May 19 Javascript
JavaScript新增样式规则(推荐)
Jul 19 Javascript
javascript cookie的基本操作(添加和删除)
Jul 24 Javascript
使用重写url机制实现验证码换一张功能
Aug 01 Javascript
JS中Object对象的原型概念基础
Jan 29 Javascript
Vue中computed与methods的区别详解
Mar 24 Javascript
layui select获取自定义属性方法
Aug 15 Javascript
jquery validate 实现动态增加/删除验证规则操作示例
Oct 28 jQuery
解决vue组件没显示,没起作用,没报错,但该显示的组件没显示问题
Sep 02 Javascript
Javascript webpack动态import
Apr 19 Javascript
JS创建Tag标签的方法详解
Jun 09 #Javascript
JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)
Jun 09 #Javascript
JS实现的随机排序功能算法示例
Jun 09 #Javascript
JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结(整理)
Jun 09 #jQuery
JQuery.dataTables表格插件添加跳转到指定页
Jun 09 #jQuery
基于代数方程库Algebra.js解二元一次方程功能示例
Jun 09 #Javascript
JavaScript 中调用 Kotlin 方法实例详解
Jun 09 #Javascript
You might like
PHP加Nginx实现动态裁剪图片方案
2014/03/10 PHP
php关联数组快速排序的方法
2015/04/17 PHP
PHP数据库连接mysql与mysqli对比分析
2016/01/04 PHP
PHP使用pdo实现事务处理操作示例
2018/09/05 PHP
js中的window.open返回object的错误的解决方法
2009/08/15 Javascript
深入理解JavaScript系列(2) 揭秘命名函数表达式
2012/01/15 Javascript
js操纵跨frame的三级联动select下拉选项实例介绍
2013/05/19 Javascript
解析JavaScript中的标签语句
2013/06/19 Javascript
jQuery之选项卡的简单实现
2014/02/28 Javascript
jQuery制作仿Mac Lion OS滚动条效果
2015/02/10 Javascript
js实现背景图片感应鼠标变化的方法
2015/02/28 Javascript
实例讲解Jquery中隐藏hide、显示show、切换toggle的用法
2016/05/13 Javascript
JavaScript常用代码书写规范的超全面总结
2016/09/11 Javascript
JavaScript生成图形验证码
2020/08/24 Javascript
jQuery中.attr()和.data()的区别分析
2017/09/03 jQuery
微信小程序progress组件使用详解
2018/01/31 Javascript
Vue项目webpack打包部署到Tomcat刷新报404错误问题的解决方案
2018/05/15 Javascript
Vue实现push数组并删除的例子
2019/11/01 Javascript
Ant Design moment对象和字符串之间的相互转化教程
2020/10/27 Javascript
[02:31]《DAC最前线》之选手酒店现场花絮
2015/01/30 DOTA
Python定时任务sched模块用法示例
2018/07/16 Python
在PyCharm中批量查找及替换的方法
2019/01/20 Python
详解python中递归函数
2019/04/16 Python
使用TensorFlow直接获取处理MNIST数据方式
2020/02/10 Python
python语言的优势是什么
2020/06/17 Python
摄影实习自我鉴定
2013/09/20 职场文书
四年的大学生生活自我评价
2013/12/09 职场文书
公司人力资源的自我评价
2014/01/02 职场文书
2013年研究生毕业感言
2014/02/06 职场文书
模范家庭事迹材料
2014/02/10 职场文书
自动一体化专业求职信
2014/03/15 职场文书
信仰心得体会
2014/09/05 职场文书
不尊敬老师检讨书范文
2014/11/19 职场文书
吧主申请感言怎么写
2015/08/03 职场文书
Java比较两个对象中全部属性值是否相等的方法
2021/08/07 Java/Android
PYTHON使用Matplotlib去实现各种条形图的绘制
2022/03/22 Python