使用HTML5的拖放API(Drag and Drop API)结合Vue的事件处理来实现
Vue组件
<template>
<div>
<ul>
<li
v-for="(item, index) in items"
:key="item.id"
draggable="true"
@dragstart="handleDragStart(index)"
@dragover.prevent="handleDragOver(index)"
@drop="handleDrop(index)"
:class="{ 'dragging': dragIndex === index }"
>
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
{ id: 4, name: 'Item 4' },
{ id: 5, name: 'Item 5' },
],
dragIndex: null,
};
},
methods: {
handleDragStart(index) {
this.dragIndex = index;
},
handleDragOver(index) {
if (this.dragIndex !== null && this.dragIndex !== index) {
const draggedItem = this.items[this.dragIndex];
this.items.splice(this.dragIndex, 1);
this.items.splice(index, 0, draggedItem);
this.dragIndex = index;
}
},
handleDrop() {
this.dragIndex = null;
},
},
};
</script>
<style>
ul {
list-style-type: none;
padding: 0;
}
li {
padding: 10px;
margin: 5px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: move;
}
.dragging {
opacity: 0.5;
}
</style>
`draggable="true"`: 使列表项可以拖拽。
`@dragstart`: 当用户开始拖拽一个元素时触发,记录当前拖拽的元素的索引。
`@dragover.prevent`: 当拖拽的元素在另一个元素上移动时触发,阻止默认行为(默认行为是不允许放置),并处理元素的重新排序。
`@drop`: 当拖拽的元素被放置时触发,清除拖拽状态。
:class="{ 'dragging': dragIndex === index }": 为当前拖拽的元素添加一个类名,以便在样式上区分。
使用 `vuedraggable` 库
`vuedraggable` 是一个基于 `Sortable.js` 的 Vue 拖拽排序库,使用非常简单,功能强大,支持列表、网格等多种拖拽排序场景。
安装 `vuedraggable`
npm install vuedraggable
使用 `vuedraggable` 实现拖拽排序
<template>
<div>
<draggable v-model="items" tag="ul" item-key="id">
<template #item="{ element }">
<li>{{ element.name }}</li>
</template>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: {
draggable,
},
data() {
return {
items: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
{ id: 4, name: 'Item 4' },
{ id: 5, name: 'Item 5' },
],
};
},
};
</script>
<style>
ul {
list-style-type: none;
padding: 0;
}
li {
padding: 10px;
margin: 5px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: move;
}
</style>
`v-model`: 绑定数据,拖拽排序后会自动更新 `items` 数组。
`tag="ul"`: 指定外层容器的标签为 `<ul>`。
`item-key`: 为每个元素指定唯一的键(`id`),用于优化渲染。
`#item`: 使用插槽自定义每个列表项的渲染内容。
使用 `Sortable.js` 直接操作 DOM
如果你不想依赖额外的库,可以直接使用 `Sortable.js`,它是一个纯 JavaScript 库,功能强大且灵活。
安装 `Sortable.js`
npm install sortablejs
使用 `Sortable.js` 实现拖拽排序
<template>
<div>
<ul ref="sortableList">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
import Sortable from 'sortablejs';
export default {
data() {
return {
items: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
{ id: 4, name: 'Item 4' },
{ id: 5, name: 'Item 5' },
],
};
},
mounted() {
this.initSortable();
},
methods: {
initSortable() {
const el = this.$refs.sortableList;
Sortable.create(el, {
animation: 150, // 动画时长
onEnd: (evt) => {
// 拖拽结束后更新数组
const { oldIndex, newIndex } = evt;
const item = this.items.splice(oldIndex, 1)[0];
this.items.splice(newIndex, 0, item);
},
});
},
},
};
</script>
<style>
ul {
list-style-type: none;
padding: 0;
}
li {
padding: 10px;
margin: 5px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: move;
}
</style>
`Sortable.create`: 初始化拖拽排序功能。
`onEnd`: 拖拽结束后触发的事件,用于更新 Vue 的数据。
`animation`: 拖拽时的动画效果。