vue实现图标拖拽
Vue 实现图标拖拽
使用 HTML5 拖放 API
在 Vue 中实现图标拖拽可以利用 HTML5 的拖放 API。通过 draggable 属性标记可拖拽元素,并监听 dragstart、dragover 和 drop 事件。
<template>
<div>
<div
v-for="(icon, index) in icons"
:key="index"
class="icon"
draggable="true"
@dragstart="dragStart(index)"
>
{{ icon }}
</div>
<div
class="drop-area"
@dragover.prevent
@drop="drop"
>
拖拽到这里
</div>
</div>
</template>
<script>
export default {
data() {
return {
icons: ['图标1', '图标2', '图标3'],
draggedIndex: null
};
},
methods: {
dragStart(index) {
this.draggedIndex = index;
},
drop() {
if (this.draggedIndex !== null) {
const draggedIcon = this.icons[this.draggedIndex];
this.icons.splice(this.draggedIndex, 1);
this.icons.push(draggedIcon);
this.draggedIndex = null;
}
}
}
};
</script>
<style>
.icon {
width: 50px;
height: 50px;
background: #eee;
margin: 5px;
display: inline-block;
cursor: move;
}
.drop-area {
width: 200px;
height: 200px;
border: 2px dashed #ccc;
margin-top: 20px;
}
</style>
使用第三方库(如 Vue.Draggable)
Vue.Draggable 是基于 Sortable.js 的 Vue 拖拽组件,适合更复杂的拖拽需求。
安装 Vue.Draggable:
npm install vuedraggable
示例代码:
<template>
<div>
<draggable v-model="icons" group="icons" @start="drag=true" @end="drag=false">
<div v-for="(icon, index) in icons" :key="index" class="icon">
{{ icon }}
</div>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: { draggable },
data() {
return {
icons: ['图标1', '图标2', '图标3']
};
}
};
</script>
<style>
.icon {
width: 50px;
height: 50px;
background: #eee;
margin: 5px;
display: inline-block;
}
</style>
自定义拖拽逻辑
如果需要更灵活的拖拽逻辑,可以结合鼠标事件(mousedown、mousemove、mouseup)实现。
<template>
<div>
<div
v-for="(icon, index) in icons"
:key="index"
class="icon"
@mousedown="startDrag(index, $event)"
:style="{ left: positions[index].x + 'px', top: positions[index].y + 'px' }"
>
{{ icon }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
icons: ['图标1', '图标2', '图标3'],
positions: [
{ x: 0, y: 0 },
{ x: 60, y: 0 },
{ x: 120, y: 0 }
],
dragging: null,
offset: { x: 0, y: 0 }
};
},
methods: {
startDrag(index, event) {
this.dragging = index;
this.offset.x = event.clientX - this.positions[index].x;
this.offset.y = event.clientY - this.positions[index].y;
document.addEventListener('mousemove', this.onDrag);
document.addEventListener('mouseup', this.stopDrag);
},
onDrag(event) {
if (this.dragging !== null) {
this.positions[this.dragging].x = event.clientX - this.offset.x;
this.positions[this.dragging].y = event.clientY - this.offset.y;
}
},
stopDrag() {
this.dragging = null;
document.removeEventListener('mousemove', this.onDrag);
document.removeEventListener('mouseup', this.stopDrag);
}
}
};
</script>
<style>
.icon {
width: 50px;
height: 50px;
background: #eee;
margin: 5px;
position: absolute;
cursor: move;
}
</style>
注意事项
- 拖拽性能优化:对于大量图标,建议使用虚拟滚动或限制拖拽范围。
- 移动端支持:HTML5 拖放 API 在移动端兼容性较差,可能需要使用触摸事件(
touchstart、touchmove、touchend)替代。 - 数据同步:拖拽后及时更新数据状态,避免视图与数据不同步。







