使用vue2+element UI,且完全使用原生的拖拽事件,无需引入外部库。
<template>
<div class="sort-container">
<span class="title">项目排序</span>
<!-- 通过 row-class-name 为每一行动态添加行的类名 -->
<el-table
:data="projects"
row-class-name="drag-row"
@row-contextmenu.prevent
border
>
<el-table-column prop="index" label="序号" width="200">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="项目名称"></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
projects: [
{ id: '1', name: '男子10米气步枪' },
{ id: '2', name: '女子50米步枪三姿' },
{ id: '3', name: '男子双向飞碟' },
{ id: '4', name: '女子25米手枪' },
{ id: '5', name: '男子50米步枪卧射' },
],
draggingIndex: null,// 当前正在拖拽的行索引
};
},
mounted() {
// 组件挂载后添加拖拽事件
this.addDragEvents();
},
updated() {
// 数据更新后重新添加拖拽事件
// 使用 this.$nextTick 获取表格行的 DOM 元素
this.$nextTick(() => {
this.addDragEvents();
});
},
methods: {
// 添加拖拽事件
addDragEvents() {
// 获取所有带有类名 'drag-row' 的表格行
const rows = document.querySelectorAll('.drag-row');
// 遍历每一行,添加拖拽事件
rows.forEach((row, index) => {
row.draggable = true; // 设置行元素为可拖拽
// 开始拖拽时的事件处理
row.ondragstart = (event) => this.handleDragStart(event, index);
// 拖拽经过时的事件处理
row.ondragover = (event) => this.handleDragOver(event);
// 拖拽放下时的事件处理
row.ondrop = (event) => this.handleDrop(event, index);
});
},
// 处理拖拽开始事件
handleDragStart(event, index) {
this.draggingIndex = index; // 记录当前拖拽行的索引
event.dataTransfer.effectAllowed = 'move'; // 设置拖拽效果为移动
event.dataTransfer.setData('text/plain', index); // 将索引存储到拖拽数据中
},
// 处理拖拽经过事件
handleDragOver(event) {
event.preventDefault(); // 阻止默认事件,允许放置
event.dataTransfer.dropEffect = 'move'; // 设置拖拽效果为移动
},
// 处理拖拽放下事件
handleDrop(event, targetIndex) {
const sourceIndex = this.draggingIndex; // 获取开始拖拽时记录的索引
// 如果源索引和目标索引相同,直接返回
if (sourceIndex === targetIndex) return;
// 创建项目列表的副本
const projects = [...this.projects];
// 删除源位置的项目,并存储被拖拽的项目
const [movedItem] = projects.splice(sourceIndex, 1);
// 在目标位置插入被拖拽的项目
projects.splice(targetIndex, 0, movedItem);
// 更新项目列表数据
this.projects = projects;
this.draggingIndex = null; // 重置拖拽索引
},
},
};
</script>
<style lang='scss' scoped>
.sort-container{
padding: 15px;
.title{
font-size: 24px;
font-weight: bold;
}
.el-table{
margin-top: 20px;
}
}
/* 自定义拖拽行样式 */
.drag-row {
cursor: move;
user-select: none;
}
.drag-row:hover {
background-color: #f0f9ff;
}
</style>