vue2 中实现动态表单增删改查
最近项目中遇到的需求是要操作大量的表单,之前的项目中有做过这方的研究,只不过是用jquery来操作。
项目A
先简单说说以前项目A中的应用场景,可能有小伙伴儿也遇到相同的需求。A项目是公司的OA系统中有的项目,是用java的jsp渲染的页面,需求是要改成:嵌入APP中显示,前后端分离, 后端返回的内容,还不能修改, 只是后端同事做了下接口处理,返回给前端的是一大堆的表单数据。
每个表单都有多个字段表示它的属性:
- 是否可编辑
- 表单类型 (text, textarea, select, radio, checkbox, hidden等 )
- 与之联动的其他表单
- 。。。
之前的方案就是各个表单类型和字段属性进行判断,调用不同的UI组件(如时间日历选择器等)
项目B
现在遇到的项目,展示类型少很多,第一个想到的就是同样的方法,不过这次使用的是Vue的双向绑定。
以下是我在python后端项目中的经验,如果没有兴趣可以直接看最后的动态表单部分
1 python 后端项目中如何引入Vue
项目B用的是python的jinjia2的模板, 同样都是去解析数据,这种情况下怎么办呢?
1 | {% raw %} |
jinjia2中使用 raw 可以阻止解析内部的代码,这样就可以引入我们的vue模板了,这里是我写的一个dialog弹框的组件
2 定义组件
这里以dialog弹窗组件为例子,直接上代码
1 | // dialog弹框 |
动态表单组件
一般的需求是:
- 一个列表,可以实现列表的动态添加,删除。
- 列表中的每一项是动态的表单,表单个数不确定,
- 有提交功能,提交或者可以保存整个表单
- 保存的表单,通过接口调回后,回填表单,还可以再次修改、增加、删除等
1 如何生成动态表单
1 | <template v-for="item in lists"> |
我们的与后端商量好的数据格式可以是这样的;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24lists: [{
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只是其中一个动态列表。
1 | <div v-for="book in books"> |
add的方法一般是:
1 | methods: { |
这里需要注意的是,如果这份模板的数据,你是通过在data属性中定义的字段去缓存的,那有可能遇到的是你通过添加操作之后的表单的值会,会随着其中的某个表单的值一起联动。
具体原因,猜测是这里的数据已经是变成响应式的了, 又或者你 通过实例化后的值去缓存这份模板数据,可能结果还是这样。
具体代码可能是这样的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21var vm = new Vue({
data: {
books: [],
cacheTemplate: null
},
methods: {
getForms: function (argument) {
this.$http.post(url, paras).then(res => {
// 此处缓存了这份模板数据,cacheTemplate中的数据已经变成响应式的了, 此处cacheTemplate是引用类型
this.cacheTemplate = res.body.data
this.books.push(res.body.data) // 创建第一动态表单列表
}, res => {
})
},
add: function () {
// 因为是引用类型,所以cacheTemplate属性值的变化必然影响其他和它相同属性的值
this.books.push(this.cacheTemplate)
}
}
})
此处的解决方法: 是要换成深度复制。
直接上代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22var 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对象
var cacheTemplate = JSON.parse(this.cacheTemplate)
this.books.push(cacheTemplate)
}
}
})
如果觉得本文不错的话,欢迎点赞。如有问题, 大家一起交流和学习