列表拖拽排序功能
实现步骤与思路
- 创建列表数据并渲染到页面
- 列表中需添加
draggable="true" - 列表中需添加
dragstartdragenterdragenddragover事件 - 在
dragenter事件中,需要传入列表项的下标,实时进行元素的排序,排序的核心逻辑也是在dragenter中 - 代码执行的逻辑是:列表项拖拽到可放置目标时,将该拖拽的元素从原位置删除,再将拖拽的元素插入到当前可放置目标的位置
代码实现
<template>
<TransitionGroup name="list" tag="div" class="container">
<div
v-for="(item, i) in drag.list"
:key="item.id"
class="item"
draggable="true"
@dragstart="dragstart($event, i)"
@dragenter="dragenter($event, i)"
@dragend="dragend"
@dragover="dragover"
>
{{ item.name }}
</div>
</TransitionGroup>
</template>
<script lang="ts" setup>
const drag = reactive({
list: [
{ name: "a", id: 1 },
{ name: "b", id: 2 },
{ name: "c", id: 3 },
{ name: "d", id: 4 },
{ name: "e", id: 5 },
],
});
let dragIndex = 0;
const dragstart = (e: any, index: number) => {
e.stopPropagation();
dragIndex = index;
setTimeout(() => {
e.target.classList.add("moveing");
}, 0);
};
const dragenter = (e: { preventDefault: () => void }, index: number) => {
e.preventDefault();
// 拖拽到原位置时不触发
if (dragIndex !== index) {
const source = drag.list[dragIndex];
drag.list.splice(dragIndex, 1);
drag.list.splice(index, 0, source);
// 更新节点位置
dragIndex = index;
}
};
const dragover = (e: any) => {
e.preventDefault();
e.dataTransfer.dropEffect = "move";
};
const dragend = (e: any) => {
e.target.classList.remove("moveing");
//排序后的数组数据
console.log(drag.list);
};
</script>
<style lang="scss" scoped>
.item {
width: 200px;
height: 40px;
line-height: 40px;
background-color: skyblue;
text-align: center;
margin: 10px;
color: #fff;
font-size: 18px;
}
.container {
position: relative;
padding: 0;
}
.moveing {
opacity: 0;
}
/* 对移动中的元素应用的过渡 */
.list-move,
.list-enter-active,
.list-leave-active {
transition: all 0.2s ease;
}
</style>
补充:可使用Vue中 <TransitionGroup> 内置组件来添加动画效果。
使用sortable.js进行表格排序
- 安装
npm i sortablejs -S
- 使用
el-table写一个表格
<template>
<div>
<el-table id="dragTable" :data="tableData" border style="width: 800px">
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
<el-table-column label="操作" width="100">
<template #default>
<div class="handle-drag">
<el-icon>
<Sort />
</el-icon>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
// 引入sortablejs
import Sortable from "sortablejs";
// 引入icon图标
import { Sort } from "@element-plus/icons-vue";
// 表格数据源
const tableData = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "Cilly",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "Linda",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-01",
name: "John",
address: "No. 189, Grove St, Los Angeles",
},
];
// 排序
const setSort = () => {
const el = document.querySelector("#dragTable table tbody");
new Sortable(el, {
sort: true,
ghostClass: "sortable-ghost",
// 配置表示只有包含`.handle-drag` 样式的元素才可以被拖动,其他位置不能被拖动。
handle: ".handle-drag",
onEnd: (e: { oldIndex: number; newIndex: number }) => {
const targetRow = tableData.splice(e.oldIndex, 1)[0];
tableData.splice(e.newIndex, 0, targetRow);
// 排序之后的数据源
console.log(tableData);
},
});
};
onMounted(() => {
setSort();
});
</script>
<style lang="scss" scoped></style>