1、使用第三方库如:vuedraggable
(1)安装vuedraggable
npm install vuedraggable
(2)在Vue组件中使用vuedraggable
<template>
<div>
<draggable
v-model="urlPic"
@start="isDragging=true"
@end="isDragging=false"
v-bind="{animation:150,ghostClass:'sortable-ghost',chosenClass:'chosenClass',scroll:true,scrollSensitivity:200}">
<transition-group>
<div v-for="(item, index) in urlPic" :key="index">
<div @click="deletPic(index)">
<i class="el-icon-delete"></i>
</div>
<el-image :src="item.url" :preview-src-list="urlPic">
</el-image>
</div>
</transition-group>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: {
draggable
},
data() {
return {
urlPic: [
{ id: 1, name: 'Item 1', url: '1.png' },
{ id: 2, name: 'Item 2', url: '2.png' },
{ id: 3, name: 'Item 3', url: '3.png' },
],
isDragging: false
};
},
methods: {
}
};
</script>
官方文档:https://github.com/SortableJS/Vue.Draggable
中文文档:https://www.itxst.com/vue-draggable/tutorial.html
2、使用原生draggable拖拽方法
draggable=“true”,设置可拖拽属性
拖放事件总共有7个,
源元素触发事件3个:
事件 | 说明 |
---|---|
dragstart | 开始拖放 |
dragenter | 拖放过程 |
dragend | 结束拖放 |
目标元素触发事件4个。
事件 | 说明 |
---|---|
ondragenter | 当被拖放的元素进入本元素时 |
ondragover | 当被拖放的元素正在本元素范围内移动时 |
ondragover | 当被拖放的元素离开本元素时 |
ondrop | 当源元素释放到本元素时 |
<template>
<div class="root">
<transition-group tag="div" class="containers">
<div
class="item"
v-for="(files, i) in (fileList || data.image)"
:key="files.key"
draggable="true"
@dragstart="handleDragStart($event, files)"
@dragover.prevent="handleDragOver($event, files)"
@dragenter="handleDragEnter($event, files)"
@dragend="handleDragEnd($event, files)"
>
<div>
<img :src="files.url" :alt="files.name" :title="files.name" width="100px" height="100px">
<div class="img-files-name">{{files.name}}</div>
<div class="buttons image-button">
<el-button class="el-icon-search" plain @click="imageSearch(files)"></el-button>
<el-button class="el-icon-delete" plain @click="imageDelete(files)"></el-button>
</div>
</div>
</div>
</transition-group>
</div>
</template>
<script type="text/javascript">
export default {
name: 'image-preview',
data() {
return {
ending: null,
dragging: null,
fileList: null,
};
},
props: {
data: {
type: Object,
},
},
mounted() {
const { image } = this.data;
// 前端根据附件名称做下去重
if (image && image.length) {
const map = new Map(image.map(item => [item.files.name, item]));
const uniqueArr = [...map.values()];
this.$set(this, 'fileList', uniqueArr);
}
},
computed: {
},
methods: {
// 用户开始拖动元素时触发
handleDragStart(e, item) {
this.dragging = item;
},
// 用户完成元素拖动后触发
handleDragEnd() {
if (this.ending.key === this.dragging.key) {
return;
}
const newItems = [...this.data.image];
const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(this.ending);
newItems.splice(src, 1, ...newItems.splice(dst, 1, newItems[src]));
this.data.image = newItems;
this.$nextTick(() => {
this.dragging = null;
this.ending = null;
});
},
// 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
handleDragOver(e) {
// 首先把div变成可以放置的元素,即重写dragenter/dragover
// 在dragenter中针对放置目标来设置
e.dataTransfer.dropEffect = 'move';
},
// 当被鼠标拖动的对象进入其容器范围内时触发此事件
handleDragEnter(e, item) {
// 为需要移动的元素设置dragstart事件
e.dataTransfer.effectAllowed = 'move';
this.ending = item;
},
},
};
</script>
<style lang="scss" scoped>
.containers {
display: flex;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
margin: 10px;
color: #fff;
transition: all linear 0.3s;
//float: left;
.img-files-name{
top: -17px;
position: relative;
font-size: 10px;
color: #000;
width: 100px;
display: -webkit-box;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.buttons {
display: none;
.el-button {
padding: 7px 10px;
}
.el-icon-search {
//margin: 7px;
background-color:rgba(255,255,255,0.5);
}
.el-icon-download {
//margin: 7px;
background-color:rgba(255,255,255,0.5);
}
.el-icon-delete {
//margin: 7px;
background-color:rgba(255,255,255,0.5);
}
}
.image-button {
margin-left: 4px;
top: -35px;
width: 100px;
position: relative;
}
.file-button {
margin-top: 30px;
width: 100px;
position: relative;
}
}
.item:hover .buttons {
display: block;
}
</style>