背景:
elementUI 上传文件组件不支持多张图片同时上传实现排序。必须一张一张上传。影响用户体验
解决方案:
方案1:
同时上传图片的时候,在图片名称加上时间戳,上传成功之后,在根据时间戳排序。
会产生的问题:1、时间戳有时候会相同。2、顺向排序勉强实现,但想替换中间一张图片就有困难。
方案2:拖拽排序,自行拖拽排序,灵活性比较高,没有啥限制。(可以使用)
实现:
1、借助第三方拖拽组件vuedraggable
npm install vuedraggable --save
import draggable from 'vuedraggable'
components: {
draggable
},
2、封装文件上传组件
<draggable v-if="type === 'picture-drag'" :value="fileList" :animation="100" style="position: relative;margin-bottom: 10px; clear: left" @input="onDraggable">
<div v-for="(item, index) in fileList" :key="index" style="display: inline-block;float: left" class="isimages">
<div
:style="{ width: width, height: height, borderRadius: 5 + 'px' }"
style="background: white;"
>
<img
ref="preview"
z-index="999"
lazy
:loading="true"
:style="{ width: width, height: height, borderRadius: 5 + 'px' }"
:src="item.url"
>
<div class="imgs_prews">
<div
class="imgs_prew"
:style="{ width: width, height: height, borderRadius: 5 + 'px' }"
>
<i class="el-icon-zoom-in" @click="handlePictureCardPreview(item)" />
<span />
<i class="el-icon-delete" @click="handleRemove(item)" />
</div>
</div>
</div>
</div>
<el-upload
style="display: inline-block"
action="#"
:class="(fileList && fileList.length < limit)?'':'picture-uploader'"
list-type="picture-card"
class="picture-card"
:auto-upload="false"
:multiple="multiple || limit > 1"
:disabled="disabled"
:style="{'--height':height,'--width':width}"
:on-change="handlePictureChange"
:on-preview="handlePicturePreview"
:on-exceed="handleExceed"
:file-list="[]"
:limit="limit - fileList.length"
>
<div slot="default" style="position: relative;margin-top: -10px">
<i v-if=" fileList && fileList.length < limit" class="el-icon-plus" />
<div class="limit-num">{{ fileList && fileList.length }}/{{ limit }}</div>
</div>
</el-upload>
</draggable>
部分核心代码,方法自行实现。需要的prop如下
props: {
value: {
type: [Array, String],
default() {
return []
}
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
limit: {
type: Number,
default: 5
},
width: {
type: String,
default: '96px'
},
height: {
type: String,
default: '96px'
},
filePath: {
type: String,
default: 'pc/'
},
type: {
type: String,
default: () => ''
},
fileType: {
type: Array,
default: () => [] // [.png]
},
fileSize: {
type: String,
default: () => '2'
}
},
css代码:
. isimages {
position: relative;
display: inline-block;
margin-right: 8px;
}
. isimages:hover .imgs_prews {
display: block;
}
.imgs_prews {
display: none;
}
.imgs_prew {
position: absolute;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
color: #fff;
background: rgba(0, 0, 0, .3);
}
.imgs_prew I {
display: inline-block;
font-size: 20px;
cursor: pointer;
}
.imgs_prew span {
width: 2px;
height: 18px;
margin: 0 8px;
}
说明:这里有个关于v-model的问题。如果draggable使用v-model,在fileList的值是父视图传过来的,那么是无法更改父组件的值。所以用value赋值,@input自行处理事件
效果:
效果和elementUI的样式是一致的。区别只是一个可以拖拽一个不可以