elementplus结合sortablejs做出表格可拖拽效果的组件
1.安装npm install sortablejs2.在src下新建可复用的组合式函数文件夹composablessrc/composables/useSortableDrag.jsimport { ref, onMounted, onBeforeUnmount, nextTick } from vue import Sortable from sortablejs /** * 拖拽排序配置选项 * typedef {Object} SortableOptions * property {string} handle - 拖拽手柄选择器默认为 .drag-handle * property {number} animation - 动画持续时间ms默认为 150 * property {string} easing - 缓动函数默认为 cubic-bezier(0.25, 0.46, 0.45, 0.94) * property {number} scrollThreshold - 触发滚动的边缘距离px默认为 80 * property {number} scrollSpeed - 滚动速度默认为 15 * property {boolean} autoScroll - 是否启用自动滚动默认为 true * property {Function} onSort - 排序完成后的回调函数 * property {Function} onStart - 拖拽开始时的回调函数 * property {Function} onEnd - 拖拽结束时的回调函数 * property {Function} onMove - 拖拽移动时的回调函数 */ /** * 拖拽排序组合式函数 * param {string|Ref} tableRef - 表格引用 * param {RefArray} dataList - 数据列表引用 * param {SortableOptions} options - 配置选项 * returns {Object} 拖拽控制方法 */ export function useSortableDrag(tableRef, dataList, options {}) { const { handle .drag-handle, animation 150, easing cubic-bezier(0.25, 0.46, 0.45, 0.94), scrollThreshold 80, scrollSpeed 15, autoScroll true, onSort null, onStart null, onEnd null, onMove null } options let sortableInstance null let autoScrollTimer null let autoScrollDirection 0 // 0: 停止, 1: 向下, -1: 向上 const isDragging ref(false) // 停止自动滚动 const stopAutoScroll () { if (autoScrollTimer) { clearInterval(autoScrollTimer) autoScrollTimer null } autoScrollDirection 0 } // 启动自动滚动 const startAutoScroll (tableWrapper) { if (!autoScroll || autoScrollTimer) return autoScrollTimer setInterval(() { if (autoScrollDirection 0 || !tableWrapper) return const scrollTop tableWrapper.scrollTop const maxScrollTop tableWrapper.scrollHeight - tableWrapper.clientHeight let newScrollTop scrollTop autoScrollDirection * scrollSpeed // 限制滚动范围 if (newScrollTop 0) { newScrollTop 0 autoScrollDirection 0 stopAutoScroll() } else if (newScrollTop maxScrollTop) { newScrollTop maxScrollTop autoScrollDirection 0 stopAutoScroll() } tableWrapper.scrollTop newScrollTop }, 16) // 约 60fps } // 获取表格包装器 const getTableWrapper () { if (!tableRef.value) return null // 兼容不同的表格组件 if (tableRef.value.$el) { return tableRef.value.$el.querySelector(.el-table__body-wrapper) } return tableRef.value.querySelector?.(.el-table__body-wrapper) || null } // 获取表格主体 const getTableBody () { const wrapper getTableWrapper() return wrapper?.querySelector(tbody) || null } // 初始化拖拽 const initSortable () { if (!tableRef.value) { console.warn(useSortableDrag: tableRef is not ready) return } const tableBody getTableBody() const tableWrapper getTableWrapper() if (!tableBody || !tableWrapper) { console.warn(useSortableDrag: table body or wrapper not found) return } // 如果已经存在实例先销毁 destroySortable() sortableInstance Sortable.create(tableBody, { handle, animation, easing, scroll: false, // 禁用默认滚动使用自定义滚动 onStart: (evt) { isDragging.value true document.body.style.cursor grabbing if (onStart) onStart(evt) }, onMove: (evt) { if (!autoScroll) { if (onMove) onMove(evt) return } const { originalEvent } evt const clientY originalEvent.clientY if (!tableWrapper) return const rect tableWrapper.getBoundingClientRect() const relativeY clientY - rect.top // 检查是否在边缘区域 if (relativeY scrollThreshold) { // 向上滚动 autoScrollDirection -1 startAutoScroll(tableWrapper) } else if (relativeY rect.height - scrollThreshold) { // 向下滚动 autoScrollDirection 1 startAutoScroll(tableWrapper) } else { // 停止滚动 autoScrollDirection 0 stopAutoScroll() } if (onMove) onMove(evt) }, onEnd: (evt) { // 拖拽结束时停止自动滚动 stopAutoScroll() document.body.style.cursor isDragging.value false const { oldIndex, newIndex } evt if (oldIndex newIndex) { if (onEnd) onEnd(evt) return } // 移动数据 const [movedItem] dataList.value.splice(oldIndex, 1) dataList.value.splice(newIndex, 0, movedItem) if (onSort) onSort(evt, movedItem, oldIndex, newIndex) if (onEnd) onEnd(evt) } }) } // 销毁拖拽实例 const destroySortable () { if (sortableInstance) { sortableInstance.destroy() sortableInstance null } stopAutoScroll() } // 更新拖拽实例当数据变化时重新初始化 const refreshSortable () { nextTick(() { initSortable() }) } // 禁用拖拽 const disableSortable () { if (sortableInstance) { sortableInstance.option(disabled, true) } } // 启用拖拽 const enableSortable () { if (sortableInstance) { sortableInstance.option(disabled, false) } } // 设置拖拽手柄选择器 const setHandle (selector) { if (sortableInstance) { sortableInstance.option(handle, selector) } } // 生命周期钩子 onMounted(() { // 延迟初始化确保 DOM 已渲染 setTimeout(initSortable, 100) }) onBeforeUnmount(() { destroySortable() }) return { initSortable, destroySortable, refreshSortable, disableSortable, enableSortable, setHandle, isDragging, stopAutoScroll } }3.在需要用到的地方添加el-table-column aligncenter fixed width40 label template #default el-icon classdrag-handle stylecursor: grab; color: #909399 Operation / /el-icon /template /el-table-column // 使用拖拽排序功能 const { refreshSortable } useSortableDrag(tableRef, chainTableList, { handle: .drag-handle, animation: 150, autoScroll: true, scrollThreshold: 80, scrollSpeed: 15, disabled: false }) async function getData() { …… refreshSortable() }

相关新闻

CTFSHOW-WEB(萌新18-22)

CTFSHOW-WEB(萌新18-22)

web18 1.本题比上一题多过滤了一个file,但是和上一题的思路一样:Nginx 访问日志路径 /var/log/nginx/access.log 不包含 php、file 这两个被拦截字符串,所以上一题的日志投毒方法依然可以直接使用。 2.按照上面的思路,我们直接进…

2026/8/4 14:07:12 阅读更多 →
腾讯云OpenClaw智能开发平台一键部署与优化指南

腾讯云OpenClaw智能开发平台一键部署与优化指南

1. OpenClaw与Clawdbot项目概述 OpenClaw(又称Clawdbot)是腾讯云生态中快速崛起的一站式智能开发平台,它通过模块化技能包(Skills)和可视化编排能力,让开发者能够快速构建AI应用。这个平台最吸引人的特点在…

2026/8/4 14:07:12 阅读更多 →
低代码平台选型:交付能力与可视化开发的平衡之道

低代码平台选型:交付能力与可视化开发的平衡之道

1. 低代码平台的本质矛盾:交付能力与可视化开发的博弈 在2023年企业数字化转型调研报告中,一个令人震惊的数据是:采用低代码平台的企业中,有67%的项目最终未能达到预期业务目标。而在这67%的失败案例中,89%的问题根源并…

2026/8/4 14:07:11 阅读更多 →

最新新闻

行业洞察系列 06 | 汽车制造的视觉革命

行业洞察系列 06 | 汽车制造的视觉革命

维视智造 行业洞察系列 06 汽车制造的视觉革命 AI视觉在新能源车与智能驾驶全产业链的深度应用 2026年8月 维视智造 战略部 出品标杆案例:上汽通用 长城汽车 中车集团 **摘要:**中国新能源汽车产销量已连续多年全球第一,整车制造、动力电…

2026/8/4 15:09:42 阅读更多 →
SpringBoot+Vue全栈社区养老服务平台开发实践

SpringBoot+Vue全栈社区养老服务平台开发实践

1. 项目背景与核心价值 人口老龄化已成为全球性社会问题,我国60岁以上人口占比已超过18%。这个基于SpringBootVue的全栈社区服务管理平台,正是针对老年群体日常生活痛点的数字化解决方案。我在实际开发中发现,传统社区服务存在三大短板&#…

2026/8/4 15:09:42 阅读更多 →
GPT-5.6 Sol与Fable 5实测对比:开发者如何选择最适合的代码生成与推理模型

GPT-5.6 Sol与Fable 5实测对比:开发者如何选择最适合的代码生成与推理模型

当开发者面对琳琅满目的大语言模型时,最常问的问题不是“哪个模型最厉害”,而是“哪个模型最适合我手头的任务”。是写代码、做分析、处理长文档,还是日常对话?不同的模型在特定场景下的表现天差地别,盲目追求“最强”…

2026/8/4 15:09:42 阅读更多 →
C++11统一列表初始化与std::initializer_list详解

C++11统一列表初始化与std::initializer_list详解

1. 从C98到C11:初始化方式的演进之路 在C98标准中,初始化操作一直是个令人头疼的问题。不同场景下的初始化语法差异巨大,新手经常被各种初始化方式搞得晕头转向。让我们先回顾一下C98时代的初始化方式: // 结构体初始化 struct …

2026/8/4 15:09:42 阅读更多 →
IoTDB在储能运维中的时序数据库选型与实践

IoTDB在储能运维中的时序数据库选型与实践

1. 从数据保管到数据驱动:储能运维的范式转变 在新能源行业摸爬滚打多年,我亲眼见证了储能系统运维从"被动响应"到"主动预防"的进化历程。传统运维平台就像个尽职的图书管理员——它们把设备数据分门别类地存放好,等出了…

2026/8/4 15:09:41 阅读更多 →
Godot项目逆向工程实战:从PCK包与字节码恢复可编辑源码

Godot项目逆向工程实战:从PCK包与字节码恢复可编辑源码

1. 项目概述:当你的Godot项目“失联”时在游戏开发这条路上,我见过太多同行因为一次误操作、一次硬盘故障,或者仅仅是接手一个“祖传”的、只有导出包的Godot项目而陷入困境。你手头可能只有一个孤零零的.pck文件,或者一堆看似天书…

2026/8/4 15:08:41 阅读更多 →

日新闻

AI Agent白手起家26: 使用标准事件驱动大模型实践

AI Agent白手起家26: 使用标准事件驱动大模型实践

纲要 练习目标:掌握大模型标准事件的调用回顾 LangChain 中的核心标准事件 invokestreambatchastream_eventswith_structured_output 环境准备实战代码:多种事件调用对比 同步调用与流式输出批量处理异步事件流监听结构化输出 运行说明与预期结果总结与扩…

2026/8/4 0:00:40 阅读更多 →
dealsea是什么?跨境卖家必知的美国deal站入门指南

dealsea是什么?跨境卖家必知的美国deal站入门指南

说实话,第一次听说美国这个老牌折扣网站的跨境卖家,十个有八个会问同一个问题:这个平台到底是干嘛的?我见过一个做家居出口的朋友,他在亚马逊上月销二十万美金,却从来没用过它。我给他看了首页——一屏一屏…

2026/8/4 0:01:40 阅读更多 →
清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

通讯作者:邓兵、刘建国通讯单位:清华大学DOI:https://doi.org/10.1021/acs.est.6c00603研究背景稀土元素(REEs)是清洁能源技术与电子器件不可或缺的核心原料,然而传统提取方式依赖能耗高、排放大的采矿与强…

2026/8/4 0:01:40 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/4 13:24:41 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/4 11:41:39 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/4 5:26:40 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/4 13:38:24 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/4 11:09:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/4 13:38:40 阅读更多 →