1. 使用第三方组件库 vuedraggable
npm i -S vuedraggable
举一个多列拖拽的例子,剩下的属性和列子可以去链接文档查询,文档还是很全的。
// 多列拖拽
<template>
<div class="drag">
<div class="col-md-3">
<draggable class="list-group" tag="div" v-model="list" v-bind="dragOptions" :move="onMove" @start="isDragging=true" @end="isDragging=false">
<transition-group type="transition" :name="'flip-list'">
<div class="item" v-for="element in list" :key="element.order">
<i :class="element.fixed? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'" @click=" element.fixed=! element.fixed" aria-hidden="true" />
{{element.name}}
<span class="badge">
{{element.order}}
</span>
</div>
</transition-group>
</draggable>
</div>
<div class="col-md-3">
<draggable element="span" v-model="list2" v-bind="dragOptions" :move="onMove">
<transition-group name="no" class="list-group" tag="ul">
<div class="item" v-for="element in list2" :key="element.order">
<i :class="element.fixed? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'" @click=" element.fixed=! element.fixed" aria-hidden="true"></i>
{{element.name}}
<span class="badge">{{element.order}}</span>
</div>
</transition-group>
</draggable>
</div>
</div>
</template>
<script>
import draggable from "vuedraggable";
const message = [
"vue.draggable",
"draggable",
"component",
"for",
"vue.js 2.0",
"based",
"on",
"Sortablejs"
];
export default {
components: {
draggable
},
data() {
return {
list: message.map((name, index) => {
return { name, order: index + 1, fixed: false };
}),
list2: [],
editable: true,
isDragging: false,
delayedDragging: false
};
},
computed: {
dragOptions() {
return {
animation: 300,
group: "description",
disabled: !this.editable,
ghostClass: "ghost"
};
}
},
}
</script>
ps:vuedraggable这个包里引入了 element-ui,所以万一项目本身很大的话,还是不推荐使用了吧,不然打的包又要大很多。
2. 使用 draggable 属性 + transition-group
draggable:一个元素可以被拖放需要设置 draggable
属性为true
(文本、图片和链接的draggable
默认就是true
)
<div draggable="true">能被拖放的元素</div>
设置了这个属性的元素就能实现拖拽效果了,但是实现拖拽并放置还不行,还需要处理配合其他方法,如下:
触发对象 | 事件名称 | 说明 |
---|---|---|
源对象 | dragstart | 源对象开始被拖动时触发 |
drag | 源对象被拖动过程中反复触发 | |
dragend | 源对象拖动结束时触发 | |
目标对象 | dragstart | 源对象开始进入目标对象范围内触发 |
dragover | 源对象在目标对象范围内移动时触发 | |
dragleave | 源对象离开目标对象范围时触发 | |
drop | 源对象在目标对象范围内被释放时触发 |
<template>
<div>
// transition-group 使拖拽效果更加流畅
<transition-group class="trans" name="trans-list" tag="div">
// 遍历元素,给每个元素添加 draggable 属性
<div class="item" v-for="(item,index) in apps" :key="item.order" :draggable="item.fixed ? false : true" @dragstart="drag($event,index,item)" @dragend="dragend($event)" @dragenter="dragenter($event)" @dragleave="dragleave($event)" @dragover="allowDrop($event)" @drop="drop($event,index)">
<span @click.stop.prevent="changeMove(item)">{{item.fixed ? '固定' : '可动'}}</span>
{{item.title}}
</div>
</transition-group>
</div>
</template>
<script>
import _ from 'lodash'
export default {
name:'hardWorld',
data(){
return{
apps:[
{
title:'空我',
order:1
},
{
title:'亚吉托',
order:2
},
{
title:'龙骑',
order:3
},
{
title:'555',
order:4
},
{
title:'剑',
order:5
},
{
title:'响鬼',
order:6
},
{
title:'甲斗',
order:7
},
{
title:'电王',
order:8
},
{
title:'月骑',
order:9
},
{
title:'帝骑',
order:10
},
],
// 当前拖拽元素的下标
indexS:null,
}
},
methods:{
// 修改元素 draggable 属性,false为不能拖拽
changeMove(data){
this.$set(data,'fixed',!data.fixed)
},
// 拖拽,保存当前拖拽元素的下标
// 更改拖拽元素的透明度,使其与其他元素从视觉上区分开来
drag(e,index,data){
if(data.fixed){
return
}
this.indexS = index;
e.target.style.opacity = 0.5;
},
// 拖拽结束,拖拽元素的半透明度去掉,恢复原状
dragend(e){
e.target.style.opacity ='';
},
// 拖拽元素进入当前节点范围时,给目标元素添加一个背景色
dragenter(e){
if (e.target.className === 'item') {
e.target.style.background = 'purple';
}
},
// 拖拽元素离开当前节点范围时,去掉背景色
dragleave(e){
if (e.target.className === 'item') {
e.target.style.background = '';
}
},
// 拖拽元素在当前节点范围内移动时触发
// 阻止目标节点触发默认操作
allowDrop(e){
e.preventDefault()
},
// 释放拖拽元素,获取目标元素的下标
// 将拖拽元素原位置的值进行删除,并将其插入至新目标元素的位置
drop(e,index){
e.preventDefault();
e.target.style.background = '';
let moved=_.cloneDeep(this.apps[this.indexS])
let moveTarget=_.cloneDeep(this.apps[index])
if (index>-1 && index!==this.indexS && !moveTarget.fixed) {
this.apps.splice(this.indexS,1)
this.apps.splice(index,0,moved)
}
}
}
}
</script>
<style scoped>
.trans{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.trans-list-move{
transition: transform .3s;
}
.item{
width:19%;
margin: 5px 0;
background-color: #eee;
}
</style>
简单的拖拽demo就完成了,当然还能在这基础上实现更好的效果,可以随意发挥!