当前位置: 首页 > news >正文

el-table结合sortablejs实现行拖拽时禁止特定行移动

1. 为什么需要禁止特定行拖拽?

在实际开发中,我们经常会遇到需要固定表头或者某些特殊数据行的场景。比如表格的第一行可能是汇总行,或者某些行包含关键数据不允许用户随意调整顺序。这时候就需要在实现拖拽功能的同时,对特定行进行保护。

我最近在一个后台管理系统项目中就遇到了这样的需求:表格的第一行是统计汇总数据,需要始终固定在顶部不被拖动。刚开始尝试直接用sortablejs实现拖拽时,发现所有行都能被拖动,这显然不符合业务需求。经过一番摸索,终于找到了可靠的解决方案。

2. 基础环境准备

2.1 安装必要依赖

首先确保你的Vue项目中已经安装了Element Plus和sortablejs:

npm install element-plus sortablejs --save

如果你使用的是Vue 2.x版本,需要安装对应版本的Element UI:

npm install element-ui sortablejs --save

2.2 基础表格结构

我们先创建一个基础的el-table组件,包含一些示例数据:

<template> <div class="draggable-container"> <el-table :data="tableData" row-key="id" style="width: 100%" :row-class-name="rowClassName" > <el-table-column prop="name" label="姓名" width="180" /> <el-table-column prop="gender" label="性别" width="180" /> <el-table-column prop="age" label="年龄" /> </el-table> </div> </template> <script setup> import { ref } from 'vue' import Sortable from 'sortablejs' const tableData = ref([ { id: 1, name: '汇总行', gender: '-', age: '-' }, { id: 2, name: '张三', gender: '男', age: 25 }, { id: 3, name: '李四', gender: '女', age: 22 }, { id: 4, name: '王五', gender: '男', age: 30 } ]) </script>

3. 实现拖拽功能的核心逻辑

3.1 初始化sortablejs

在onMounted生命周期钩子中初始化sortablejs:

const rowClassName = ({ row, rowIndex }) => { return rowIndex !== 0 ? 'draggable-row' : 'fixed-row' } onMounted(() => { const tbody = document.querySelector('.draggable-container .el-table__body-wrapper tbody') Sortable.create(tbody, { draggable: '.draggable-row', onEnd({ newIndex, oldIndex }) { const currRow = tableData.value.splice(oldIndex, 1)[0] tableData.value.splice(newIndex, 0, currRow) } }) })

这里的关键点是:

  1. 通过rowClassName方法给可拖拽行添加特定类名
  2. 在Sortable.create配置中指定只有带有draggable-row类的行可以被拖动

3.2 样式优化

为了让固定行和可拖拽行有更明显的视觉区分,我们可以添加一些CSS:

.fixed-row { background-color: #f5f7fa; cursor: not-allowed; } .draggable-row { cursor: move; }

4. 进阶实现方案

4.1 动态控制可拖拽行

有时候我们需要根据行数据动态决定是否允许拖动,比如只允许管理员拖动某些行:

const rowClassName = ({ row }) => { return row.allowDrag ? 'draggable-row' : 'fixed-row' } const tableData = ref([ { id: 1, name: '汇总行', gender: '-', age: '-', allowDrag: false }, { id: 2, name: '张三', gender: '男', age: 25, allowDrag: true }, { id: 3, name: '李四', gender: '女', age: 22, allowDrag: false }, { id: 4, name: '王五', gender: '男', age: 30, allowDrag: true } ])

4.2 处理多级表头的情况

如果你的表格使用了多级表头,需要调整选择器来正确获取tbody:

onMounted(() => { const tbody = document.querySelector('.draggable-container .el-table__body-wrapper table tbody') // 其余代码保持不变 })

5. 常见问题与解决方案

5.1 拖拽后数据更新不及时

有时候拖拽完成后,表格数据没有及时更新。这是因为Vue的响应式系统可能没有检测到数组变化。解决方案是:

onEnd({ newIndex, oldIndex }) { const newData = [...tableData.value] const [removed] = newData.splice(oldIndex, 1) newData.splice(newIndex, 0, removed) tableData.value = newData }

5.2 固定多行的情况

如果需要固定多行(比如前两行),可以这样修改rowClassName:

const rowClassName = ({ rowIndex }) => { return rowIndex > 1 ? 'draggable-row' : 'fixed-row' }

5.3 拖拽性能优化

当表格数据量较大时,拖拽可能会出现卡顿。可以考虑以下优化措施:

  1. 使用虚拟滚动
  2. 减少拖拽时的样式计算
  3. 对大数据表格进行分页处理

6. 完整代码示例

下面是一个完整的实现示例,包含了所有核心功能:

<template> <div class="draggable-container"> <el-table :data="tableData" row-key="id" style="width: 100%" :row-class-name="rowClassName" > <el-table-column prop="name" label="姓名" width="180" /> <el-table-column prop="gender" label="性别" width="180" /> <el-table-column prop="age" label="年龄" /> </el-table> </div> </template> <script setup> import { ref, onMounted } from 'vue' import Sortable from 'sortablejs' const tableData = ref([ { id: 1, name: '汇总行', gender: '-', age: '-', allowDrag: false }, { id: 2, name: '张三', gender: '男', age: 25, allowDrag: true }, { id: 3, name: '李四', gender: '女', age: 22, allowDrag: true }, { id: 4, name: '王五', gender: '男', age: 30, allowDrag: true } ]) const rowClassName = ({ row }) => { return row.allowDrag ? 'draggable-row' : 'fixed-row' } onMounted(() => { const tbody = document.querySelector('.draggable-container .el-table__body-wrapper tbody') Sortable.create(tbody, { draggable: '.draggable-row', onEnd({ newIndex, oldIndex }) { const newData = [...tableData.value] const [removed] = newData.splice(oldIndex, 1) newData.splice(newIndex, 0, removed) tableData.value = newData } }) }) </script> <style> .fixed-row { background-color: #f5f7fa; cursor: not-allowed; } .draggable-row { cursor: move; } </style>

7. 实际应用中的注意事项

在真实项目中使用这个方案时,有几个关键点需要注意:

  1. 浏览器兼容性:sortablejs在现代浏览器中表现良好,但在一些旧版本IE中可能需要polyfill
  2. 移动端适配:如果需要支持移动端触摸操作,确保测试触摸拖拽的体验
  3. 数据持久化:拖拽顺序变更后,记得将新顺序保存到后端
  4. 无障碍访问:为拖拽操作添加适当的ARIA属性,提升无障碍体验

我在最近的一个项目中就遇到了移动端适配的问题,发现部分安卓设备上拖拽不灵敏。最终通过调整sortablejs的touchStartThreshold参数解决了这个问题。

http://www.jsqmd.com/news/542437/

相关文章:

  • Windows下OpenClaw安装避坑:百川2-13B量化模型对接详解
  • 快速上手CosyVoice2:无需代码,网页操作,轻松克隆声音做配音
  • 别再乱接18650电池了!手把手教你DIY一个8V/5000mAh的移动电源(附电路图与安全要点)
  • VSCode + Cortex-Debug嵌入式调试全攻略:从settings.json到launch.json的完整配置流程
  • 给Unity萌新的C#版本选择指南:2024年新项目到底该用Unity哪个版本?
  • HP-Socket技术演讲视频描述撰写指南:关键词与吸引力
  • SoybeanAdmin国际化:多语言支持与本地化实践
  • Windows Insider计划离线管理命令行工具:安全切换与高效管理指南
  • SWF逆向工程认证考试复习指南:JPEXS Free Flash Decompiler重点整理
  • SEO_从零开始构建网站SEO体系的完整方案
  • Repomix CLI命令大全:所有参数选项详解
  • 如何为Rainmeter贡献多语言翻译:完整指南
  • 终极指南:如何使用Mermaid.js创建太空探索任务规划与系统架构图表
  • Linux exec进程替换详解
  • Llama-3.2V-11B-cot部署案例:中小企业低成本构建AI图文分析工作台
  • 5分钟快速上手:GetQzonehistory免费备份QQ空间所有历史说说
  • Particle Life模式探索指南:5个技巧发现前所未见的美学形态
  • 三极管基极下拉电阻在高速电路中的关键作用解析
  • 告别虚拟机!在Windows上用Navicat直连Ubuntu 20.04的MySQL 8.0,完整权限配置指南
  • 告别网络依赖:用这个开源工具+高德离线包,5步搞定前端地图离线展示
  • JPEXS Free Flash Decompiler社区大使选拔流程:申请与评审完全指南
  • HP-Socket社区贡献者奖励发放确认流程:接收与反馈
  • 新手也能懂的RAIM算法:用Python复现GNSS完好性监测(附代码与数据)
  • 如何为Obsidian Sample Plugin添加插件设置默认值:终极指南
  • 告别卡顿闪烁!在Cesium 1.134中集成SOG格式,让400万高斯秒级加载
  • Linux静态库与共享库(动态库)详解
  • Repomix构建流程解析:TypeScript编译与打包的完整指南
  • 2026年写饮品广告的广告语委托/告语优化/广告语服务/广州广告语策划优质公司推荐 - 品牌宣传支持者
  • ccmusic-database新手教程:Gradio输出组件定制——增强Top5结果可读性技巧
  • UEFI安全启动恢复流程文档:详细操作指南与故障排除