VUE-element开发实现无限生成明细组件
功能需求概述:仿造钉钉审批中,在钉钉微应用中实现无限生成明细模块的功能。其中会涉及到的问题如下:
1.无限生成的明细怎么实现
2.form表单的校验问题
3.生成的组件如何取值
4.后面还有一个查看明细的功能,所以要求这一块的开发,明细这部分必须是可复用。并且还涉及到一部分控制其中的样式问题。
例如下图中点击“增加明细”按钮就会生成一个明细填写的表单,移除就会移除这个明细。
一.无限生成的明细怎么实现
无限生成明细在JSP中真的挺头疼的。使用VUE开发能够很好的完成这部分。主要涉及到VUE的核心思想:组件化。
这部分开发参考了这个帖子,并且做了优化为了校验
参考帖
因为考虑到复用的问题。我把明细单独写成了一个VUE,并且从父类中通过v-for去动态生成和调用这个模块。
先上父模块的调用:
表单中直接添加
<el-button type="success" @click="addDetail()">添加明细</el-button>
<detail v-for="(item, index) in RMform.RDform" :key="index" @deleteIndex="deleteDetail" :index="index" :item="item"></detail>
data中里面无限生成的模块数组存放的地方。
RMform:{//receiveManagement对象为表单对象:RMform
receiveId:null, //int not null comment '领用单id',
receivePostion:null, // varchar(4) comment '领用地点(1.泺立 2.赛皓达)',
receiveType:null, // varchar(4) comment '领用类别(1.办公用品 2.固定资产 3.礼品 4.其他)',
deptId:null, // varchar(64) comment '部门id',
deptName:null, // varchar(64) comment '部门名称',
purpose:null, // varchar(128) comment '物品用途',
remarks:null, // varchar(256) comment '备注',
images:null, // varchar(2048) comment '最多9张,保存图片的url,多个url用;隔开',
status:null, // varchar(64) comment '审批状态',
userId:null, // varchar(64) comment '发起人id',
launchTime:null, // datetime comment '发起时间',
userName:null, // varchar(64) comment '发起人姓名',
orderCode:null, // varchar(64) comment '审批单编号',
receivedeptname:null, //‘领用部门名称’
receivedeptid:null, //‘领用部门id’
RDform:[{ //数组:用来装载生成的明细
id:null, //int not null comment 'id',
receiveNumber:null, //int comment '领用数量',
receiveId:null, // int comment '所属领用单id',
goodsId:null, // int comment '领用物品id',
goodsName:null //varchar '领用物品名称'
}],
},
调用的两个方法
deleteDetail(index){//删除一条明细
if (index !== 0) {
this.RMform.RDform.splice(index, 1)
}
},
addDetail(){//添加一条明细
this.RMform.RDform.push({})
},
因为是成品,所以中间遇到的很多坑都被我挖掉了。所以和参考帖有很多明显的不同。
- 这里用的v-for是遍历,表里的RMform.RDform就是被动态生成的明细,在这里被动态生成的组件必须被声明为一个数组。声明可以什么为空
例如:RDform:[{}],但是一定要声明。因为增加和删除明细实际上是对这一个数组对象做增加或减少1个数组元素的操作。 - 然后这里用的detail标签是引入的声名为detail的vue组件。所以这里需要import和componts一下才行,名字可以自己改不影响。
- 说说v-for后面那车东西::key,:index和:item,@deleteIndex=“deleteDetail”。
:key:这个循环当中生成的每一个组件的唯一标识。这里使用下标确保唯一性
:index和:item:这两个都是一个东西。代表的是父页面传给子页面的两个参数:‘index’和‘item’
然后等号后面是其对应的内容。那么子页面如下图这样接收:
@deleteIndex=“deleteDetail”:这个是父页面传到子页面的方法。代表的是父页面将等号后面的deleteDetail这么一个方法传到子页面,子页面接收的时候调用的是@后面的内容。
通过 $emit调用。这个方法第一个字符串参数对应父页面传到子页面的方法名,即@后面的内容,如果方法要参数就加逗号传参。这里前面也讲了,增加和删除明细实际上是对这一个数组对象做增加或减少1个数组元素的操作。删除因为要传具体的删除对象下标所以参数传个下标就好了。
二.FORM表单的校验问题
还是因为是成品的原因。这部分当初开发时,RDform这个明细数组是定义在RMform外面的,所以当初遇到了一个问题就是说你在父页面拿他form对象的validate()方法返回的valid的bollean值是没有考虑到动态生成里面的内容,也就是说如果你的明细增加了校验规则的话,无论你填没填明细里面的内容,父页面form对象的validate()方法都会忽略掉明细的校验。
所以当初研究出了一个解决的方法,但是最优解还是把RDform这个明细数组定义在RMform中。正好他们也是两个表而且是一对多关系。
这是detail组件中全部代码截图。
校验主要涉及对应校验行当中两个属性。:prop和:rules,这两个都是有冒号的,缺少会导致无法校验。
- :prop: 基本上是通过这个让父页面的validate()方法找到你这个对象。这边他的规则是
:prop="'RDform.' + index +'.goodsName'"
,RDform是v-for绑定的数组来自父页面,index是索引,goodsName是表单绑定的v-model的名称,然后用.把他们链接起来。 - :rules: 这个绑定你要校验的规则。这个是直接一一对应校验规则没有办法偷懒
到此如果再说一下,我这边的校验。
这个是我提交表单的校验。可以看到是必须要有一个vaild才能进行下一步的,this.$refs[formName].validate((valid)
这个方法就是触发一个表单校验,通过form表单定义的ref属性值然后使用它的validate方法,如果没有问题就会返回TRUE,有问题时返回FALSE并且前端也会有红字出现。
这个我相信很多人都懂,其实这个还和表单当中对应每一个项的prop属性有关,而子页面的校验当中,:prop属性还和父页面v-model的双向绑定有关。是不是发现了一个知识的漏洞
所以当初开发的时候苦思冥想怎么正确校验子页面的表单时发现。最好的方法其实就是把遍历的那个数组对象直接放到父页面绑定的那个表单对象里面。就像这样。
RMform:{
RDform:[{ }]
}
这样就可以正确校验子页面并且返回正确的vaild值。
三.生成的明细怎么取值
这个和VUE的组件化思路有关。子页面每一个input都双向绑定了父页面的PDform对象。你直接在父页面当中看PDform数组对象就会发现,你填什么,PDform就会对应什么。每一个input对应一条明细当中的一个属性,每个明细模块对应一条PDform对象,这些都是水到渠成的东西。
四.模块复用
模块复用功能嘛,当然要把模块当中的一些没用的提示语去掉,按钮和input设置不可编辑之类的。
经过之前的开发,动态生成反而变成最简单的。这里不多说了,上个图自己看吧
然后的话是吧明细里面的下方小字设置隐藏以及按钮和input设置不可编辑。
这部分首先必须要拿到对象,然后就…。自己console.log()一下咯 直接上代码。
/* 打开弹窗触发事件 */
hideBtn(){
this.$refs['detailsDialog'].$children[0].disabled=true;
for (detail of this.$refs['detailsDialog'].$children[0].$children) {
detail.$data.noticeIsShow=false;
}
},
我这边通过在当前页面调用this.$refs['detailsDialog'].$children[0]
拿到明细的表单对象,然后就简单了。
改需求了,改需求了。。。。后面想到什么再补充吧