以 Element 树表格为例,实现了树表格的同级之间排序(跨级也有代码,但还有问题)

踩坑点:

  • onMove回调中 oldIndex 会随时变化,若想拿到最开始拖动的Row,需要使用onChoose 。
  • 在onChoose需将 oldIndex 或者 oldRow 存储一下,供后续onMove和onEnd使用。
  • onMove 中可以使用return false 阻止拖动
  • 因为是树形结构,所以回调中返回的 Index 并不准确,所以要预先在onChoose 时将树数据扁平化,才能根据返回的Index获取到对应的Row。
  • 拖动结束更改树表格源数据,虽然数据有更改,但视图可能会乱掉,所以要使用nexttick 更新数据
  • 更新数据后默认树会缩合,所以要设置需要展开的节点

上代码

<el-tableref="ruleSelectTableRef"v-loading="isLoading"row-key="ruleTagId":data="tableData"border:max-height="500"
><el-table-column label="" width="45"></el-table-column><el-table-column width="40" :render-header="selectAllHeaderRender"><template slot-scope="scope"><el-checkboxv-model="scope.row.isSelected":disabled="scope.row.isDisabled"@change="val => selectRow(val, scope.row)"></el-checkbox></template></el-table-column><el-table-column label="设备类" prop="packageName"></el-table-column><el-table-column label="操作" prop="handles" width="80" fixed="right"><template slot-scope="scope"><el-buttonv-if="scope.row.level !== 1"type="text":class="{ 'text-btn-red': scope.row.compareOnline }"@click="showLogModule(scope.row)">查看日志</el-button></template></el-table-column>
</el-table>import Sortable from 'sortablejs';
import { deepClone } from '@/utils/util';
import { nextTick } from 'process';private selectedTableData: IListRuleCollectionRuleSelectInfo[] = [];
private flatSelectedTableData: any[] = [];
private drawOldIndex: any = -1;// 将树数据转化为平铺数据
flatTreeData(treeData: any[], childKey = 'children') {const arr: any[] = [];const expanded = (data: any) => {if (data && data.length > 0) {data.filter((d: any) => d).forEach((e: any) => {arr.push(e);expanded(e[childKey] || []);});}};expanded(treeData);return arr;
}// 行拖拽
rowDrop() {// 此时找到的元素是要拖拽元素的父容器const tbody = document.querySelector('#selected-table .el-table__body-wrapper tbody');const that = this;Sortable.create(tbody, {// 指定父元素下可被拖拽的子元素draggable: '.el-table__row',setData: function (dataTransfer: any) {dataTransfer.setData('Text', '');},onChoose({ oldIndex }: any) {// 把树形的结构转为列表再进行拖拽that.$set(that, 'flatSelectedTableData', that.flatTreeData(that.selectedTableData));that.drawOldIndex = oldIndex;},onMove({ related }: any) {const oldRow: any = that.flatSelectedTableData[that.drawOldIndex];const newRow: any = that.flatSelectedTableData[related.rowIndex];// if (!newRow || !newRow.id || !oldRow || !oldRow.id) return false;// 拖动的是一个包if (oldRow.level === 1) {if (newRow.level === 1 && oldRow.id === newRow.id) return false;// 还在自己的包里面if (oldRow.rulePackageId === newRow.newPackageId) return false;} else {// 不是包不可以挪到最上面if (related.rowIndex === 0) return false;// 跨包不允许if (oldRow.newPackageId !== newRow.newPackageId || newRow.level === 1) return false;}},onEnd({ newIndex, oldIndex }: any) {if (oldIndex !== newIndex) {const oldRow: any = that.flatSelectedTableData[oldIndex];const newRow: any = that.flatSelectedTableData[newIndex];const selectedTableData = deepClone(that.selectedTableData);that.selectedTableData = [];const expansionRowKey: any[] = [];// 拖动的是一个包if (oldRow.level === 1) {expansionRowKey.push(oldRow.id);// 找到拖动的这个包const currPackageIndex = selectedTableData.findIndex((p: any) => p.id === oldRow.id);// 找到新包的位置塞进去// 新位置是一个包的位置 (包 -> 包)if (newRow.level === 1) {const newPackageIndex = selectedTableData.findIndex((p: any) => p.id === newRow.id);const currPackage = selectedTableData.splice(currPackageIndex, 1)[0];selectedTableData.splice(newPackageIndex, 0, currPackage);expansionRowKey.push(newRow.id);// 新位置是一个行的位置 (包 -> 行)} else {// 找到这个行的父级包const newPackageIndex = selectedTableData.findIndex((p: any) => p.newPackageId === newRow.newPackageId);// 删掉原来的包,放到新包的后面const currPackage = selectedTableData.splice(currPackageIndex, 1)[0];selectedTableData.splice(newPackageIndex, 0, currPackage);expansionRowKey.push(selectedTableData[newPackageIndex].id);}// 拖动的是一个行} else {// 新目标是一个包 (行 -> 包)if (newRow.level === 1) {expansionRowKey.push(newRow.id);// 如果还是原来的包(包内排序移到开头)if (oldRow.newPackageId === newRow.newPackageId) {// 找到当前包位置const newPackageIndex = selectedTableData.findIndex((p: any) => p.id === newRow.id);const currPackage = selectedTableData[newPackageIndex];expansionRowKey.push(currPackage.id);const currPackageChildren = currPackage?.children || [];// 找到拖动的行在children 中的 indexconst currRuleIndex = currPackageChildren.findIndex((rule: any) => rule.ruleTagId === oldRow.ruleTagId);const currRule = currPackageChildren.splice(currRuleIndex, 1)[0];// 放到最开头currPackageChildren.splice(0, 0, currRule);currPackage.children = currPackageChildren;// 替换掉原来的包selectedTableData.splice(newPackageIndex, 1, currPackage);// 如果在另外一个包开头(废弃,目前不允许,还有问题)} else {return false;// 找到旧包// const oldPackageIndex = selectedTableData.findIndex((p: any) => p.newPackageId === oldRow.newPackageId);// const oldPackage = selectedTableData[oldPackageIndex];// expansionRowKey.push(oldPackage.id);// const oldPackageChildren = oldPackage?.children || [];// // 删掉旧包中的 old rule// const oldRuleIndex = oldPackageChildren.findIndex((rule: any) => rule.ruleTagId === oldRow.ruleTagId);// const oldRule = oldPackageChildren.splice(oldRuleIndex, 1)[0];// // 找到新包// const newPackageIndex = selectedTableData.findIndex((p: any) => p.id === newRow.id);// const newPackage = selectedTableData[newPackageIndex];// const newPackageChildren = newPackage?.children || [];// // 新包中增加 该 rule// newPackageChildren.splice(0, 0, oldRule);// // 覆盖原包// oldPackage.children = oldPackageChildren;// newPackage.children = newPackageChildren;// selectedTableData.splice(oldPackageIndex, 1, oldPackage);// selectedTableData.splice(newPackageIndex, 1, newPackage);}// 新位置是一个行的位置 (行 -> 行)} else {// 还在原来的包内(包内排序)if (oldRow.newPackageId === newRow.newPackageId) {// 找到当前包位置const newPackageIndex = selectedTableData.findIndex((p: any) => p.newPackageId === newRow.newPackageId);const currPackage = selectedTableData[newPackageIndex];expansionRowKey.push(currPackage.id);const currPackageChildren = currPackage?.children || [];// 找到拖动的行在children 中的 indexconst oldRuleIndex = currPackageChildren.findIndex((rule: any) => rule.ruleTagId === oldRow.ruleTagId);// 找到将要排序到的目标位置const newRuleIndex = currPackageChildren.findIndex((rule: any) => rule.ruleTagId === newRow.ruleTagId);// 排序const oldRule = currPackageChildren.splice(oldRuleIndex, 1)[0];currPackageChildren.splice(newRuleIndex, 0, oldRule);currPackage.children = currPackageChildren;// 替换掉原来的包selectedTableData.splice(newPackageIndex, 1, currPackage);// 在另外一个包内(废弃,目前不允许,还有问题)} else {return false;// 找到旧包// const oldPackageIndex = selectedTableData.findIndex((p: any) => p.newPackageId === oldRow.newPackageId);// const oldPackage = selectedTableData[oldPackageIndex];// expansionRowKey.push(oldPackage.id);// const oldPackageChildren = oldPackage?.children || [];// // 删掉旧包中的 old rule// const oldRuleIndex = oldPackageChildren.findIndex((rule: any) => rule.ruleTagId === oldRow.ruleTagId);// // 找到新包// const newPackageIndex = selectedTableData.findIndex((p: any) => p.newPackageId === newRow.newPackageId);// const newPackage = selectedTableData[newPackageIndex];// expansionRowKey.push(newPackage.id);// const newPackageChildren = newPackage?.children || [];// // 找到 newRule 在 新包中的 index// const newRuleIndex = newPackageChildren.findIndex((rule: any) => rule.ruleTagId === newRow.ruleTagId);// const oldRule = oldPackageChildren.splice(oldRuleIndex, 1)[0];// // 新包中增加 该 rule// newPackageChildren.splice(newRuleIndex, 0, oldRule);// // 覆盖原包// oldPackage.children = oldPackageChildren;// newPackage.children = newPackageChildren;// selectedTableData.splice(oldPackageIndex, 1, oldPackage);// selectedTableData.splice(newPackageIndex, 1, newPackage);}}}that.$nextTick(() => {that.selectedTableData = selectedTableData;that.$nextTick(() => {that.selectedTableData.forEach((item: any) => {if (expansionRowKey.includes(item.id)) {(that.$refs.ruleSelectedTableRef as any).toggleRowExpansion(item, true);}});});});}},});
}

觉得有帮助的小伙伴记得点个赞鼓励下~

扫描上方二维码关注我的订阅号~

踩坑日记 - Sortable 拖动树表格排序相关推荐

  1. 【踩坑日记】阿里云表格存储

    1. 禁用主键列的自增列功能!禁用主键列的自增列功能!!禁用主键列的自增列功能!!!重要的事情要说三遍 2. 自增列一旦设置,无法人为填充,只能依赖表格存储的自增功能,所以建议使用自定义发号器 3. ...

  2. 全志哪吒D1-H Tina Linux Ubuntu 22.04入门踩坑日记

    哪吒D1-H Tina Linux入门踩坑日记 系统环境 源码编译 mklibs-readelf的C++标准问题 m4的SIGSTKSZ问题 libfakeroot的_STAT_VER问题 read_ ...

  3. Antd Pro V4 protable详解(ps:踩坑日记)

    Antd Pro V4 protable详解(ps:踩坑日记) 写在前面: 在这篇文章中,你会了解到: protable 中的cloumns属性详解 protable数据加载和处理(两种方法,直接使用 ...

  4. Win11 + Ubuntu18.04 双系统踩坑日记

    Win11 + Ubuntu18.04 双系统踩坑日记 前言 准备工作 硬件配置 镜像下载 Win11镜像下载 Ubuntu镜像下载 启动盘准备 Win11启动盘 Ubuntu启动盘 Win11安装 ...

  5. 【Flutter混合开发踩坑日记之‘applicationVariants‘ for extension ‘android‘】

    Flutter混合开发踩坑日记之'applicationVariants' for extension 'android' 正文 坑一:Could not get unknown property ' ...

  6. Swarm-BZZ踩坑日记之 如何让METMASK小狐狸显示gbzz

    刚入门bzz的新手还不知道小狐狸是什么的请移步上一章节:Swarm-BZZ踩坑日记之 如何在METMASK小狐狸导入节点地址 在浏览器安装好小狐狸,并添加自己的钱包地址后 会发现只显示ETH,并不显示 ...

  7. ReactNative 在丁香医生项目中引入的踩坑日记

    ReactNative 在丁香医生项目中引入的踩坑日记 this没绑定到函数导致空指针 参考 React-Native 踩坑第二弹-undefined is not a function(evalua ...

  8. springboot踩坑日记—nacos: Error watching Nacos Service change

    springboot踩坑日记-nacos: Error watching Nacos Service change Spring Boot :: (v2.1.5.RELEASE) 错误代码: 07-3 ...

  9. 微信小程序踩坑日记-微信小程序首次加载样式错乱问题

    微信小程序踩坑日记-微信小程序首次加载样式错乱问题 在实际开发项目中,遇到了个棘手的问题,就是在某些因素下,进入小程序发现有些样式发生偏移.错乱等问题 问题原因:-未知(估计是组件的问题) ↓ 解决办 ...

最新文章

  1. docker 网络 实现
  2. 模式识别与智能系统和计算机视觉,天津大学模式识别与智能系统
  3. CG-CTF-Web-bypass again
  4. Qt编写数据可视化大屏界面电子看板12-数据库采集
  5. python读json文件中不同的数据类型_怎么使用python提取json文件中的字段
  6. 钉钉 ISV 应用开发的一些心得
  7. Kubernetes-NodePort(十七)
  8. JavaScript模拟call和apply的实现
  9. 笔记72 高级SSM整合
  10. NUC1011 Financial Management【数学计算+水题】
  11. Bootstrap 3.2.0 源码试读 2014/08/14
  12. python割圆法求“圆周率”
  13. 计算机硬盘格式化了如何恢复出厂设置,怎么把电脑格式化?
  14. 为什么要在信号线上串联一些小电阻
  15. 【Uipath杂谈】用Datatable处理数据(二)
  16. 利用python炒股talib_【手把手教你】股市技术分析利器之TA-Lib(一)
  17. 【渝粤题库】陕西师范大学292951 公司金融学Ⅱ 作业(专升本)
  18. 唐朝一体机屏幕显示变红
  19. Xamarin iOS 切换开发者账号之后的签名标识和预配配置文件更新方法
  20. 计算机专业英语实战记录(整理了上千个相关单词)

热门文章

  1. Vscode 代码状态颜色块不见
  2. 哪个抢票软件抢票成功率高?
  3. 信号(三)Kill函数和Kill命令
  4. 前端项目上线相关配置
  5. webP编码图片基础
  6. 碳排放数据查询网站汇总-权威
  7. 【Vue】Vue 项目前、后端整合(图表二:产品月销曲线堆叠图)
  8. 第三方登录的作用、价值与实现方式
  9. Python Celery异步快速下载股票数据!炒股还怕输吗?
  10. 修改 数据库服务器 密码是什么原因,怎么改数据库服务器密码是什么原因