sortablejs
https://juejin.cn/post/7572161976592990260
模板结构
vue
<template>
<el-table ref="typeTableRef" :data="filteredTypeData" stripe row-key="id">
<!-- 排序列:显示拖拽图标 -->
<el-table-column label="排序" width="131">
<template #default>
<el-icon class="drag-handle">
<Operation />
</el-icon>
</template>
</el-table-column>
<!-- 其他列 -->
<el-table-column prop="name" label="名称" />
<el-table-column prop="enabled" label="启用/禁用">
<template #default="{ row }">
<el-switch v-model="row.enabled" />
</template>
</el-table-column>
</el-table>
</template>核心实现代码
js
// 表格引用
const typeTableRef = ref<InstanceType<typeof ElTable>>();
// Sortable 实例(用于后续销毁)
let sortableInstance: Sortable | null = null;
/**
* 初始化拖拽排序功能
*/
const initSortable = () => {
// 1. 销毁旧实例,避免重复创建
if (sortableInstance) {
sortableInstance.destroy();
sortableInstance = null;
}
// 2. 等待 DOM 更新完成
nextTick(() => {
// 3. 获取表格的 tbody 元素
const tbody = typeTableRef.value?.$el?.querySelector(
".el-table__body-wrapper tbody"
);
if (!tbody) return;
// 4. 创建 Sortable 实例
sortableInstance = Sortable.create(tbody, {
// 指定拖拽手柄(只能通过拖拽图标来拖拽)
handle: ".drag-handle",
// 动画时长(毫秒)
animation: 300,
// 拖拽结束回调
onEnd: ({ newIndex, oldIndex }) => {
// 5. 更新数据顺序
if (newIndex !== undefined && ldIndex !== undefined && filterStatus.value === "all") {
// 只在"全部"状态下允许排序
// 获取被移动的项
const movedItem = typeData.value[oldIndex];
// 从原位置删除
typeData.value.splice(oldIndex, 1);
// 插入到新位置
typeData.value.splice(newIndex, 0, movedItem);
// 更新排序字段
typeData.value.forEach((item, index) => {
item.sortOrder = index + 1;
});
}
}
});
});
};生命周期管理
js
/**
* 监听标签页切换,初始化拖拽
*/
const watchActiveTab = () => {
if (activeTab.value === "type") {
// 延迟初始化,确保表格已完全渲染
setTimeout(() => {
initSortable();
}, 300);
}
};
// 组件挂载时初始化
onMounted(() => {
watchActiveTab();
});
// 监听标签页切换
watch(activeTab, () => {
watchActiveTab();
});
// 监听过滤器变化,重新初始化拖拽
watch(filterStatus, () => {
if (activeTab.value === "type") {
setTimeout(() => {
initSortable();
}, 100);
}
});样式定义
/* 拖拽手柄样式 */
.drag-handle {
color: #909399;
cursor: move;
font-size: 18px;
transition: color 0.3s;
}
.drag-handle:hover {
color: #1890ff;
}
/* 表格样式 */
.type-table {
margin-top: 0;
}
:deep(.type-table .el-table__header-wrapper) {
background-color: #f9fafc;
}
:deep(.type-table .el-table th) {
background-color: #f9fafc;
font-size: 14px;
font-weight: 500;
color: #33425cfa;
font-family: PingFang SC;
border-bottom: 1px solid #dcdfe6;
}使用sortablejs拖拽排序 视图显示与数据不一致、拖拽结束后回跳
数据的顺序是对的,视图是乱的 https://juejin.cn/post/7370841518792015907
CAUTION
v-for循环一定要给一个唯一的key!!! 不能偷懒用index,害我搞半天
el-table 需要设置row-key="fieldKey",默认使用index
// 重新赋值来刷新视图 (这里我调的父组件的变量,你的可以换成当前组件的变量)
that.$parent.moduleList = [] // 必须有此步骤,不然拖拽后回弹
that.$nextTick(function () {
that.$parent.moduleList = newArray // 重新赋值,用新数据来刷新视图
console.log(that.moduleList)
})