1. 拖拽的实现
1.dom操作
原本已经封装好的elementui来说,它的图片是一个fileList的数组,而拖拽的话,需要对dom进行操作,因此,我们首先想到的是能否取到img的src并将其放在一个div中,循环遍历显示出我们上传后的图片(下文中的fileArray只是一个假定值,代表我们在data里面定义的这个model值)1
2
3<div v-for="item in fileArray">
<img src="item中存放的地址">
</div>
这里要说的是,已经上传成功的response值和我们在上传图片成功时的返回值的数据结构并不一样。因此我们需要想办法取其共同点并且构造成一个新的数组,得到我们的fileArray。1
2
3
4
5fnBsnUploadPicSuccess(response, file, fileList) {
if (response && response.result && response.result.res_path) {
this.fileArray = this.fileArray.concat(response.result);
}
}
2.拖拽
这个直接利用组件去实现,最开始的时候我选用的是vue.draggable,star还不错,效果也有,但是问题出现了,保存之后的结果依然是未排序之前的?这,难道它只实现了拖拽效果,而没有实现排序之后的数据结构的改变?尴尬了。我要去怎么搞?再搞一插件?给每个类都加一个class?来存储这排序之后的东西么?网上查了很久,也没有发现特别有用的,有些垂直列表之类的可以利用偏移值,然而我这是不确定的一个个排列下来的行内元素啊。突然转机,发现一个感觉还可以的插件,既能排序,也能保存,开心。立马抛弃了之前的vue.draggable,换上了新的vue-dragging。效果也是棒棒哒~开心!好景不长!当我把这个插件用到同一个页面中的另一个功能相同的组件中时,报错了!这里面一个非常关键的值就是找不到!悲伤的是,这个并不晓得去哪里解决这个问题,而且发现issue里面也有和我类似的问题,,,悲伤,,,好吧,再次回归到vue.draggable,star这么多一定是有的它的道理,而且人家应该也会考虑到这种问题吧。认真看了它的文档,重要的是down下它的demo。好吧,傻的人家有model用来存放他们的顺序。1
2
3
4
5<draggable v-model="myArray" :options="{draggable:'.item'}">
<div v-for="item in fileArray">
<img src="item中存放的地址">
</div>
</draggable>
其中myArray就是用来存放顺序的数组,options呢暂时还没有发现它的作用。折腾来折腾去又回到了原点。
- 学习一个插件最快的方式是它的demo
- 插件的话,一定要选择可用性可维护性更强的。
- 文档要好好读
3.图片的查看
直接将图片放入一个对话框,并且通过查看按钮控制对话框的显示与隐藏即可。1
2
3
4
5// 点击查看图片,注意此时还是利用数组下标来实现
fnClickPreviewPic(index) {
this.布尔值 = true;
this.sImgUrl = 图片地址
},
4.删除
与查看相似利用数组的原生方法即可1
2
3
4// 删除图片
fnBsnRemovePic(index) {
this.fileArray.splice(index, 1);
},
5. 类似elementui的遮罩层和按钮的实现
这个网站还不错,很多hover效果大家都可以好好参考一下
利用tranform和opacity,比较关键的点就是元素hover之后对其他标签做的效果。1
2
3
4<div class="mask mask1")>
<i class="el-icon-zoom-in"></i>
<i class="el-icon-delete"></i>
</div>
拖拽并没有单独做一个按钮,因为其实它的效果并不是你点到某个按钮才会去实现这个效果。而是随便点到图片的某个地方即可,因此只是将鼠标的样式改成了move。这样可能会和上面的按钮冲突,因此我们将按钮的点击区域设置为一个固定的很小的地方,在这里面cursor为pointer,而其他地方我们则给他换回move。
以上步骤都完成之后,看似很完美,但是如果你需要对上传的总数做限制,那么你就happy了,这个limit真的是脑细胞都要死光了。
2.让我想砸电脑的limit
elementui里面实现一个这个真的是很简单啊,如果你设置了limit为一个数之后,只要它超过这个数,就是走到on-exceed函数。然而,我们现在弃用了它,只保留了上传的功能,如果只是将它设置为一个固定值,是肯定不行滴。
think one
因为我们能得到这次上传的值,以及我们已经上传的值,如果它超过这个值,就抛出错误,这样好像很完美,ok,试之。ok,为limit绑定一个值num,并且在初始化时将它的值设置为总长度-已经上传的图片数量
,每次上传成功或者删除图片时都去修改这个值。ok,开始时没有问题,可是当我们删除几个再次添加时候函数走到on-exceed。失败~
think two
不绑变量了,ok,我们直接给他设置成总长度-已经上传的图片数量
,并且我打印了这个值,嗯嗯,看起来好像很符合要求,简单试了一下上传多个的,ok,完全没有问题啊,就在我以为问题解决了而窃喜的时候,问题又来了、、、,如果我此时已经上传了4张,限制数量为6张,limit此时为3,而我即使只是上传一张,也没有成功。。。各个环节都没有问题啊,到底是为什么。
think three
在on-success中直接对fileArray做剪切,只显示其中的前6个,ok,这样确实看起来起到了效果,但是问题是,这些图片已经全部上传成功,对后端服务的压力很大,也并不符合我们设计的初衷。
think four
before-upload,这个函数是我曾经一度想使用看看的,可以在上传图片之前对图片做处理。如果超出限制,可以避免think three中的问题,然而,这个函数每上传一张都会执行一次,我们可以去维护一个变量监测到底有没有超出limit,但是当我们批量上传的时候,它可能还是存在只是没有超出limit的图片上传成功,而后面的都失败了,这样的用户体验并不好。也许排在后面的才是我们想上传的。
think five
想来想去,还是要从limit入手。到底为什么删删传传几次之后即使 要上传的数量<limit
还是会执行on-exceed函数呢???后面查了很多资料,有些不太记得了,elementui的源码中,封装的这个函数的源码,如果files的长度+fileList的长度>limit
那么就会执行这个函数。ok算是有点思路了,毕竟知道问题处在哪里,就有一点点儿方向了。
删除上传的时候,我们并没有对fileList做操作。导致它可能会有一个累加的效果。因此,我们要对这一部分数据做处理。1
limit长度=限制长度 - fileArray的长度 + fileList.length;
这大概是最核心的地方了。虽然只有一行代码。
自己测试了一下,暂时并没有发现什么问题。
3.写在最后
- 也许当你想修改一个东西的时候,搞清它的原理很重要,毕竟知己知彼方能百战不殆
- 要想学一个陌生的东西,demo是个不错的快速上手的方式
- 选择是一个很重要的方式,有些东西不必坚持,不必备选,有些需要坚持。看它的star值不值得了。
- 不得不说的是,写这个东西真的花费了我很多的时间,确实最后代码量并没有多少,让人觉得你可能有偷懒的成分在里面,但是我并不想因此被别人否定如果它的时间与代码的长度不成正比。因为我真的有认真思考这个东西。
- 有些你觉得不可能的事情还是会实现,比如这个东西我真的很想放弃它