由于 Element UI 的 Upload 上传组件只支持多图上传,但并不支持图片的顺序调整,而实际使用场景中,例如,产品封面轮播图,经常要用到图片顺序调整功能。所以,找了一下解决方案。
一些备选方案
JQuery UI sortable
效果演示,参考:https://codepen.io/malkafly/pen/gbVYZb
上面示例中使用的排序组件是 jquery ui 中的 sortable 功能。
但是,我测试的过程中,感觉 jquery ui 的这个功能非常不流畅,经常出现没有响应的情况。
Sortablejs
找到一个竞品 sortablejs, 从对比视频上看,优化效果明显。里面有视频演示,及对比:https://sortablejs.github.io/Sortable/
而且有 vue 版本的实现。
Vue draggable 项目地址:https://github.com/SortableJS/Vue.Draggable
带删除按钮的 vue draggable 实现:https://jsfiddle.net/dede89/5Leuhh1n/
代码实现
我觉得使用 Element UI upload 组件结合 Vue draggable 来实现上传后的图片调整顺序。
补充:结合使用,还间接修复了一个 Element UI upload 的一个巨大缺陷,即,无法同时上传多张图片。因为,选择多张图片上传时,upload 组件的 on-success 回调,只会被调用一次。最简单的解决方案是,将 file-list 去掉,引入了 draggable 之后,不再需要 upload 组件来管理删除,和排序,所有 file-list 去掉,没有任何额外工作量。
效果 Gif 截图:
实现代码
注意,这是一个基于 Laravel PHP 模板的代码,vue 变量为了避免冲突,在变量前加上了 @ 符号。转换的时候,需要去掉
模板代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Element UI 上传组件结合 Vue Draggable 实现拖拽排序</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!-- Set render engine for 360 browser -->
<meta name="renderer" content="webkit">
<!-- 禁止百度移动搜索转码 -->
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.4.0/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.4.11/theme-chalk/index.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/animate.css/3.7.0/animate.min.css" />
<link rel="stylesheet" href="{{ URL::asset('css/footer.css') }}?t=201812061243">
<style type="text/css">
input.el-upload__input {
display: none;
}
</style>
</head>
<body>
<div class="container" style="margin-bottom: 20px;">
<h1>Element UI 上传组件结合 Vue Draggable 实现拖拽排序</h1>
</div>
<div class="container" id="upload_images">
<p>
由于默认的 Element UI upload 组件不支持多图上传后的拖拽排序。
</p>
<p>
所以,测试一下 Element UI upload 组件 + Vue Draggable 来实现排序功能。
</p>
<p>
Vue Draggable 是基于 sortablejs 实现的,所以操作体验上相对 jQuery UI Sortable 要流畅很多。
</p>
<div class="row">
<div class="col-sm-12 col-md-12 main">
<el-upload
class="upload-demo"
action=""
multiple
:limit="10"
:on-success="handle_success"
list-type="picture-card"
:file-list="images">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">上方为 element ui upload 组件自带的列表样式,不支持拖拽排序</div>
</el-upload>
<div class="drag">
<h2>Vue Draggable - 可在下方尝试拖拽</h2>
<ul class="el-upload-list el-upload-list--picture-card">
<draggable v-model="images" class="dragArea">
<li :tabindex="index" class="el-upload-list__item is-success animated" style=""
v-for="(element, index) in images"
v-bind:class="{flash: element.to_del}"
>
<img :src="element.url" alt="" class="el-upload-list__item-thumbnail ">
<a class="el-upload-list__item-name">
<i class="el-icon-document"></i>
@{{element.name}}
</a>
<label class="el-upload-list__item-status-label">
<i class="el-icon-upload-success el-icon-check"></i>
</label>
<i class="el-icon-close"></i>
<span class="el-upload-list__item-actions"><!---->
<span class="el-upload-list__item-delete">
<i class="el-icon-delete" @click="remove(index)"></i>
</span>
</span>
</li>
</draggable>
</ul>
</div>
<div style="margin-bottom: 50px;">
<h2>列表数据</h2>
<div >
<p v-for="(element, index) in images">
@{{element.name}} - @{{element.url}}
</p>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
<script type="text/javascript" src="https://cdn.staticfile.org/Sortable/1.8.1/Sortable.min.js"></script>
<script type="text/javascript" src="https://cdn.staticfile.org/Vue.Draggable/2.17.0/vuedraggable.min.js"></script>
<script type="text/javascript" src="https://cdn.staticfile.org/element-ui/2.4.11/index.js"></script>
<script type="text/javascript" src="{{ asset('js/upload_images_and_sort.js') }}?t=201901212007"></script>
</body>
</html>
vuejs 代码
new Vue({
el: "#upload_images",
data: {
images: [
{
name: 'img1',
to_del: false, // 纯粹为了删除特效,可不加
url: 'http://temp.im/401x401/4CD964/fff'
},
{
name: 'img2',
to_del: false,
url: 'http://temp.im/402x402/4CD964/fff'
},
{
name: 'img3',
to_del: false,
url: 'http://temp.im/403x403/4CD964/fff'
},
{
name: 'img4',
to_del: false,
url: 'http://temp.im/404x404/4CD964/fff'
}
]
},
mounted: function() {
},
methods: {
handle_success: function() {
},
remove: function(index) {
var that = this;
this.$confirm('确认删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function () {
that.$message({
type: 'success',
message: '删除成功!'
});
that.images[index].to_del = true;
setTimeout(function() {
that.images.splice(index, 1);
}, 1000);
})
}
}
})
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式
谈笑风生
啊是大 (来自: 中国 北京 北京 鹏博士) 5年前
大象 (来自: 中国 山东 烟台 联通) 5年前
mystry (来自: 中国 广东 广州 移动) 5年前
大象 (来自: 中国 山东 烟台 联通) 5年前
旅行者 (来自: 中国 香港) 5年前
骆驼 (来自: 中国 广东 东莞 电信) 5年前
大象 (来自: 中国 山东 烟台 电信) 5年前
skx (来自: 中国 吉林 长春 联通) 4年前