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

sortablejs el-table 树结构拖拽

最近要实现el-table的树状结构的列表拖拽功能
第一步:安装sortablejs

npm install sortablejs --save

第二步:在需要的页面引入

import Sortable from 'sortablejs'

第三步:表格样式布局

 <el-table
        :data="treeTableData"
        ref="dragTable"
        class="draggable"
        row-key="id"
        border
        highligh-current-row
        :expand-row-keys="treeTableExpandKeys"
        @expand-change="treeTableExpandChange"
        @selection-change="handleSelectionChange"
        default-expand-all
      >
      <el-table-column type="selection" width="55" :selectable="selectableMethod" />
        <el-table-column prop="date" label="Date" />
        <el-table-column prop="name" label="Name" />
        <el-table-column prop="address" label="Address" />
        <el-table-column prop="handel" label="排序">
          <template #default="{}">
            <el-icon class="drag-hander" :size="20"><Rank /></el-icon>
          </template>
        </el-table-column>
      </el-table>

第四步:数组定义

 data() {
    return {
      treeTableData: [
        {
          id: 1,
          date: '2016-05-02',
          name: 'wangxiaohu',
          address: 'No. 189, Grove St, Los Angeles',
        },
        {
          id: 2,
          date: '2016-05-04',
          name: 'wangxiaohu',
          address: 'No. 189, Grove St, Los Angeles',
        },
        {
          id: 3,
          date: '2016-05-01',
          name: 'wangxiaohu',
          address: 'No. 189, Grove St, Los Angeles',
          children: [
            {
              id: 31,
              date: '2016-05-06',
              name: 'wangxiaohu',
              address: 'No. 189, Grove St, Los Angeles',
              children: [
                {
                  id: 33,
                  date: '2016-05-08',
                  name: 'LIDAHAI',
                  address: 'No. 189, Grove St, Los Angeles',
                },
                {
                  id: 34,
                  date: '2016-05-09',
                  name: 'WANGJIUN',
                  address: 'No. 189, Grove St, Los Angeles',
                },
              ],
            },
            {
              id: 32,
              date: '2016-05-07',
              name: 'wangxiaohu',
              address: 'No. 189, Grove St, Los Angeles',
            },
          ],
        },
        {
          id: 4,
          date: '2016-05-03',
          name: 'wangxiaohu',
          address: 'No. 189, Grove St, Los Angeles',
        },
      ],
      treeProps: { checkStrictly: false, children: 'children', hasChildren: 'hasChildren' },
      flatTreeData: [],
      treeTableExpandKeys: [],
      sortableObj: null,
    };
  },

第五步:初始化方法

 mounted() {
    this.transverseNode(this.treeTableData, 1, (node, level, parentNode) => {
      node.level = level;
      node.parentId = parentNode ? parentNode.id : -1;
    });
    this.initSortable();
    this.getFlatNode(this.treeTableData, this.flatTreeData);
  },

第六步:方法

methods: {
    initSortable() {
      const tbody = document.querySelector('.draggable .el-table__body-wrapper tbody');
      if (!tbody) {
        return;
      }
      Sortable.create(tbody, {
        // Sortable 配置项
        draggable: '.draggable .el-table__row',
        onEnd: this.handleSortEnd, // 处理拖拽结束后的逻辑
      });
    },
    handleSortEnd(event) {
      if (event.oldIndex !== undefined && event.newIndex !== undefined) {
        // const { oldIndex, newIndex } = event;
        // const movedItem = this.tableData.splice(oldIndex, 1)[0];
        // this.tableData.splice(newIndex, 0, movedItem);

        const { newIndex, oldIndex } = event;
        const dragRow = this.flatTreeData[oldIndex];
        const relatedRow = this.flatTreeData[newIndex];
        if (dragRow.parentId !== relatedRow.parentId) {
          this.$message.warning('只能同层级内排序');
          this.reRender(null, 'treeTableData');
        } else {
          // 都无children
          if (!dragRow.children && !relatedRow.children) {
            const oldData = this.flatTreeData.splice(oldIndex, 1)[0];
            this.flatTreeData.splice(newIndex, 0, oldData);
          }

          // drag有, relate无
          if (dragRow.children && !relatedRow.children) {
            const oldData = this.flatTreeData.splice(oldIndex, 1)[0];
            this.flatTreeData.splice(newIndex, 0, oldData);

            if (newIndex < oldIndex) {
              // 有子元素的,子元素需要同样跟上来
              const flatChildren = [];

              this.getFlatNode(oldData.children || [], flatChildren);
              if (flatChildren.length > 0) {
                for (let i = 1, len = flatChildren.length; i <= len; i++) {
                  const childData = this.flatTreeData.splice(oldIndex + i, 1)[0];
                  this.flatTreeData.splice(newIndex + i, 0, childData);
                }
              }
            } else {
              // 有子元素的,子元素需要同样跟下来
              const flatChildren = [];

              this.getFlatNode(oldData.children || [], flatChildren);
              if (flatChildren.length > 0) {
                for (let i = 1, len = flatChildren.length; i <= len; i++) {
                  const childData = this.flatTreeData.splice(oldIndex, 1)[0];
                  this.flatTreeData.splice(newIndex, 0, childData);
                }
              }
            }
          }

          // drag无, relate有
          if (!dragRow.children && relatedRow.children) {
            const oldData = this.flatTreeData.splice(oldIndex, 1)[0];
            this.flatTreeData.splice(newIndex, 0, oldData);

            if (newIndex > oldIndex) {
              // 有子元素的,子元素需要同样跟上来
              const flatChildren = [];

              this.getFlatNode(relatedRow.children || [], flatChildren);
              if (flatChildren.length > 0) {
                for (let i = 1, len = flatChildren.length; i <= len; i++) {
                  const childData = this.flatTreeData.splice(newIndex + i, 1)[0];
                  this.flatTreeData.splice(newIndex + i - 1, 0, childData);
                }
              }
            }
          }

          // drag有, relate有
          if (dragRow.children && relatedRow.children) {
            if (newIndex < oldIndex) {
              const oldData = this.flatTreeData.splice(oldIndex, 1)[0];
              this.flatTreeData.splice(newIndex, 0, oldData);

              // 有子元素的,子元素需要同样跟上来
              const flatChildren = [];

              this.getFlatNode(oldData.children || [], flatChildren);
              if (flatChildren.length > 0) {
                for (let i = 1, len = flatChildren.length; i <= len; i++) {
                  const childData = this.flatTreeData.splice(oldIndex + i, 1)[0];
                  this.flatTreeData.splice(newIndex + i, 0, childData);
                }
              }
            } else {
              const oldData = this.flatTreeData.splice(oldIndex, 1)[0];

              // relateRow的children数
              const relateFlatChildren = [];
              this.getFlatNode(relatedRow.children || [], relateFlatChildren);

              this.flatTreeData.splice(newIndex + relateFlatChildren.length, 0, oldData);

              // 有子元素的,子元素需要同样跟下来
              const flatChildren = [];

              this.getFlatNode(oldData.children || [], flatChildren);
              if (flatChildren.length > 0) {
                for (let i = 1, len = flatChildren.length; i <= len; i++) {
                  const childData = this.flatTreeData.splice(oldIndex, 1)[0];
                  this.flatTreeData.splice(newIndex + relateFlatChildren.length, 0, childData);
                }
              }
            }
          }

          // 重新生成树的数据
          const data = this.getTreeData(this.flatTreeData, []);
          console.log('this.flatTreeData', this.flatTreeData, data);
          // 页面重新渲染
          this.reRender(data, 'treeTableData');
        }
      }
    },

    getFlatNode(nodes, flatList, childrenKey = 'children') {
      nodes.forEach(node => {
        flatList.push(node);
        if (node[childrenKey] && node[childrenKey].length) {
          this.getFlatNode(node[childrenKey], flatList);
        }
      });
    },
    getTreeData(nodes, resultList) {
      const childStack = [];
      let lastNode = {};
      nodes.forEach(node => {
        delete node.children;

        const pushNode = dataNode => {
          const parentNode = childStack[childStack.length - 1];
          if (parentNode) {
            parentNode.children.push(dataNode);
          } else {
            resultList.push(dataNode);
          }
        };

        if (node.level < lastNode.level) {
          childStack.length = node.level - 1;
          pushNode(node);
        } else if (node.level === lastNode.level) {
          pushNode(node);
        } else if (node.level > lastNode.level) {
          if (!lastNode.children) {
            lastNode.children = [];
          }
          childStack.push(lastNode);
          pushNode(node);
        } else {
          resultList.push(node);
        }

        lastNode = node;
      });

      return resultList;
    },
    reRender(data, dataKey) {
      if (data) {
        this[dataKey] = [];
        this.$nextTick(() => {
          this[dataKey] = data;
        });
      } else {
        const origin = [].concat(this[dataKey]);
        this[dataKey] = [];
        this.$nextTick(() => {
          this[dataKey] = origin;
        });
      }
    },
    transverseNode(nodes, level = 1, cb, parentNode, childKey = 'children') {
      nodes.forEach(node => {
        if (node[childKey] && node[childKey].length > 0) {
          this.transverseNode(node[childKey], level + 1, cb, node, childKey);
        }
        cb(node, level, parentNode);
      });
      return nodes;
    },
    treeTableExpandChange(row, expanded) {
      if (expanded) {
        this.treeTableExpandKeys.push(row.id);
      } else {
        const idx = this.treeTableExpandKeys.indexOf(row.id);
        this.treeTableExpandKeys.splice(idx, 1);
      }
    },
    handleSelectionChange(selection){
        console.log(selection); // 已选择的行数据数组
    },
    selectableMethod(row, index){
        return row.id > 0 ? true:false;
    }
  },

第七步:移除

 beforeDestroy() {
    if (this.sortableObj) {
      this.sortableObj.destroy();
    }
  },

在这里插入图片描述
参考链接:
https://blog.csdn.net/jianjian_19/article/details/120313084
https://www.jb51.net/javascript/31103517b.htm


http://www.kler.cn/a/612324.html

相关文章:

  • PHP中yield关键字的使用
  • RestTemplate远程调用接口方式
  • 什么是视图,数据库的视图本质上就是个提前写好的sql语句,创建的一个虚拟表
  • C语言中把函数声明为inline是什么意思?
  • Nginx RTMP 处理模块 (ngx_rtmp_handler.c) 详细分析
  • Go语言分布式锁实战:dlock助力构建高并发稳定系统
  • 工作流引擎Flowable介绍及SpringBoot整合使用实例
  • ubuntu服务器server版安装,ssh远程连接xmanager管理,改ip网络连接。图文教程
  • 什么是 Promise?
  • 在鸿蒙 ArkUI 中使用本地数据缓存
  • 【数学建模】(启发式算法)蚁群算法(Ant Colony Optimization)的详解与应用
  • 深入理解椭圆曲线密码学(ECC)与区块链加密
  • 蓝桥杯模拟题--约数的个数(约数和质因数的区别)
  • spring-ai ollama小试牛刀
  • DaemonSet 与 Deployment 的主要区别
  • VSCode 抽风之 两个conda环境同时在被激活
  • 数字图像处理 -- 霍夫曼编码(无损压缩)练习
  • 解决electron-builder vue 打包后element-ui字体图标不显示问题
  • Redis之缓存双写一致性理论分析
  • 数字孪生技术:重塑UI前端的未来