基于VueDraggable和Element-ui的图片拖拽改变顺序的组件
我们公司管理后台项目是使用Element-ui组件,这次需求产品要求上传的图片组允许拖拽排序,我就想用vue-draggable插件了,但是相信Element-ui的el-upload组件封装的很好,我这种菜鸟级别的前端哪里敢动,所以我就想着上传依然用el-upload,但是把上传组件的展示图片隐藏,自己根据组件的上传之后拿到的url链接自己形成图片数组,然后展示层由我们自己来写UI和vue-dr
·
我们公司管理后台项目是使用Element-ui组件,这次需求产品要求上传的图片组允许拖拽排序,我就想用vue-draggable插件了,但是相信Element-ui的el-upload组件封装的很好,我这种菜鸟级别的前端哪里敢动,所以我就想着上传依然用el-upload,但是把上传组件的展示图片隐藏,自己根据组件的上传之后拿到的url链接自己形成图片数组,然后展示层由我们自己来写UI和vue-draggable的拖拽,话不多说,上代码,直接莽!
emmm...先来两张效果图吧
<template>
<div class="com-image-drag">
<div class="button-list">
<el-button
@click="openDrag"
v-if="!drag_open"
:disabled="banner_list.length <= 1"
type="text"
size="small"
class="operation-success"
></el-button>
<el-button
@click="save"
v-if="drag_open"
type="text"
size="small"
class="operation-success"
></el-button>
<el-button
@click="cancle"
v-if="drag_open"
type="text"
size="small"
class="operation-error"
></el-button>
</div>
<div class="image-list">
<!-- 拖拽层 -->
<div class="list-wrap" v-show="drag_open">
<draggable
v-model="banner_list"
:options="{
animation: 150,
ghostClass: 'sortable-ghost',
chosenClass: 'chosenClass',
scroll: true,
scrollSensitivity: 200
}"
>
<div
class="image-item"
v-for="($item, $index) in banner_list"
:key="$index"
:style="{ backgroundImage: `url(${$item.url})` }"
></div>
</draggable>
</div>
<!-- 展示层 -->
<div class="list-wrap" v-show="!drag_open">
<div
class="image-item"
v-for="($item, $index) in banner_list"
:key="$index"
:style="{ backgroundImage: `url(${$item.url})` }"
@mouseover.prevent="$item.is_hover = true"
@mouseleave.prevent="$item.is_hover = false"
>
<div class="label" v-show="!$item.is_hover">
<i class="el-icon-upload-success el-icon-check icon-success"></i>
</div>
<div class="mask" v-show="$item.is_hover">
<i class="el-icon-delete bin" @click="deleteImage($index)"></i>
</div>
</div>
<el-upload
v-show="limit == 0 || banner_list.length < limit"
list-type="picture-card"
name="file"
class="upload-machine"
:disabled="drag_open"
:action="action()"
:on-error="onError"
:on-success="onSuccess"
:before-upload="beforeUpload"
:show-file-list="false"
:multiple="multiple"
enctype="multipart/form-data"
></el-upload>
</div>
</div>
</div>
</template>
<script>
/**
* @author LeeYunxiang
* @description 为了方便上传图片组件可拖拽排序,不改变饿了么插件的逻辑,只做视图层的展示
* @param {Array} list 图片数组
* @param {Number} limit 最多可上传几张图片
* @param {Function} action 上传接口地址
* @param {Boolean} multiple 是否批量上传
* @param {Function} beforeUpload 上传之前的回调,用于校验
* @param {Function} onSuccess 上传成功的回调函数
* @param {Function} onError 上传失败的回调函数
*/
import draggable from "vuedraggable";
export default {
name: "ComImageShow",
components: {
draggable
},
props: {
list: {
type: Array
},
limit: {
type: Number,
default: 0
},
multiple: {
type: Boolean,
default: false
},
action: {
type: Function,
default: () => {}
},
beforeUpload: {
type: Function,
default: () => {}
},
onError: {
type: Function,
default: () => {}
},
onSuccess: {
type: Function,
default: () => {}
}
},
data() {
return {
banner_list: [], //拖拽插件不建议直接改变父组件的传值,所以另建一个新数组
file_list: [], //保存开启拖拽之前排序的数组
drag_open: false //拖拽开启开关
};
},
methods: {
// 删除图片
deleteImage(i) {
this.banner_list.splice(i, 1);
this.$emit("update", this.banner_list.map(item => item.url));
},
// 开启拖拽
openDrag() {
this.file_list = JSON.parse(JSON.stringify(this.banner_list)); //数组深拷贝
this.drag_open = true;
},
// 取消拖拽
cancle() {
this.banner_list = this.file_list;
this.drag_open = false;
},
// 拖拽保存
save() {
this.$emit("update", this.banner_list.map(item => item.url));
this.drag_open = false;
}
},
mounted() {
// 初始数组拷贝
this.banner_list = this.list.map(url => {
let obj = {
url: url,
is_hover: false
};
return obj;
});
},
watch: {
// 监听父组件传值改变
list(arr) {
if (arr.length > this.limit && this.limit != 0) {
this.$message.warning(`当前最多可上传${this.limit}张图片`);
return false;
}
this.banner_list = arr.map(url => {
let obj = {
url: url,
is_hover: false
};
return obj;
});
}
}
};
</script>
<style lang="sass" scoped>
.com-image-drag
&:after
display: block
clear: both
content: ""
.image-list
float: left
&:after
display: block
clear: both
content: ""
.list-wrap
float: left
.image-item
width: 148px
height: 148px
position: relative
margin-right: 10px
margin-bottom: 10px
border: 1px solid #c0ccda
background-size: 100% 100%
border-radius: 6px
float: left
overflow: hidden
cursor: pointer
.label
width: 46px
height: 26px
background-color: #13ce66
color: #FFFFFF
transform: rotate(45deg)
text-align: center
position: absolute
right: -17px
top: -7px
.icon-success
transform: rotate(-45deg)
.mask
width: 100%
height: 100%
border-radius: 6px
background-color: rgba(0, 0, 0, 0.5)
position: relative
.bin
color: #FFFFFF
font-size: 20px
position: absolute
left: 45%
top: 43%
.upload-machine
float: left
</style>
调用例子
<template>
<image-drag
:list="file_list"
:multiple="true"
:action="uploadUrl"
:on-error="uploadError"
:on-success="bannerPicSuccess"
:before-upload="beforeAvatarUpload"
@update="updateFile">
</image-drag>
</template>
<script>
import ImageDrag from "@/components/common/ComImageDrag";
import { Loading } from "element-ui";
export default {
components: {
ImageDrag
},
data() {
return {
banner_list: [], //ele用的
file_list: [], //自己用的
bargain: {
share_image: ""
},
number: ""
};
},
methods: {
goBack() {
this.$router.go(-1);
},
// 上传图片路径
uploadUrl() {
return `${process.env.VUE_APP_API_ROOT}upload`;
},
// 图片长传-之前
beforeAvatarUpload(file) {
let self = this;
let type_arr = ["image/jpeg", "image/png"];
let type = file.type;
if (!type_arr.includes(type)) {
this.$message.error("图片格式不正确,只支持jpg和png类型图片");
return false;
}
const is_size = new Promise((resolve, reject) => {
let width = 400;
let height = 320;
let img = new Image();
img.src = window.URL.createObjectURL(file);
img.onload = () => {
let valid = img.width === width && img.height === height;
if (valid) {
Loading.service({ fullscreen: true, text: "图片上传中,请稍后" });
resolve(file);
} else {
self.$message.error("请上传400*320px大小的图片!");
reject();
}
};
});
return is_size;
},
// Banner图-成功
bannerPicSuccess(res) {
this.bargain.share_image = res.data;
Loading.service({ fullscreen: true }).close();
this.file_list.push(res.data);
},
// Banner图片上传报错
uploadError() {
this.$message.error("上传失败,请重新上传");
Loading.service({ fullscreen: true }).close();
},
updateFile(val) {
this.file_list = val;
console.log(this.file_list);
}
}
};
</script>
更多推荐
已为社区贡献1条内容
所有评论(0)