element-ui 树形表格数据增加上下移动

998 阅读3分钟

element-ui树形表格增加子级上移,下移功能

当时的需求

  • 能够拖拽子级 进行排序
  • 只能同级拖拽不能越级

vue 2.6

疑问

其实刚开始去网上找解决方案的时候, 有看到elemrnt-ui+sotable.js 得拖拽方案(双厨狂喜), 立马 npm install 进去操作,结果发现 其实对于业务来说 sortable 不符合要求 因为拖拽完成后的 onMove这个回调函数里 我要判断是否是 父级 或者说当它越级后 我要阻止这一次 拖拽 结果 当子项拖出 父级后 我返回 false 结果子项没有回复原位 而是放置到了 拖拽完成后的子项后面 因为时间也比较急所以 不想去探究原因 最后商量说是 在页面上增加上移下移按钮 进行排序 (详情可以看看这个链接)www.itxst.com/sortablejs/…

实际操作

增加按钮上移 下移功能要比拖拽好做一些, 可以点击获取数据, 流程大致 如下

Start 
--> 点击获取id 
--> 将树形数据扁平化
--> 然后找到这个id
--> 判断他是否是数组第一个还是最后一个(这两种情况不能上下移动)
--> 和上(下)一个子项交换位置 
--> 然后数据变成树形结构 将数据表格得tablelist 重新赋值 
--> Stop

这样做确实没问题 但是频繁将数据扁平化 然后又化成树形 感觉以后数据量一多肯定完蛋 (化成树形 一般来说几乎都是递归 所以正是不足所在)

解决方案

Start
-->页面初始化created() 的时候 递归一次全部树形数据 
    增加一个level 字段比方 根节点 1 根节点第一个就是 1.1 下面的节点就是依次用'.'分割
-->点击获取id
-->首先通过这个id 解析上面的level 比方1.1.1 通过换成[1,1,1]循环,
   得出tree的位置的字符串(this.list[0].children[0].children[0]),
   做判断是否是第一个或者最后一个是的话不允许上下移动
   通过eval(str) 完成数组取值
-->通过两次this.$set 方法交换上移数据 和 目标数据的值 达成上移下移效果 最后保存提交给后台
    $set 参数用eval取值出来就好
--> Stop
   下面的方法就不需要重复的将原本树形数据扁平化, 在生成树形要好的多 我少了一次递归的方法

总结

   其实普通流程可以在页面初始化的时候生成一个扁平化的数据 然后再走普通流程会少一点性能消耗, 但是还是会存在将数据变成树形的一个操作 还是没有直接查找树形数据来的方便。一次业务上的解决方案怕忘记所以记下来了, 可能还有更好的方法 希望大佬们不要喷我 能力只有这么高哈哈 但是也希望大佬们有更好的方案交流
贴一下自己的代码片段 可能只有自己看的懂 没做本地化处理啊
getTreeIndex (data) {
      let str = `this.list[]`;
      data.forEach((item, index, arr) => {
        if (index == 0) {
          str = `this.list[${arr[0] - 1}]`;
        } else {
          str = str + `.children[${arr[index] - 1}]`;
        }
      });

      return str;
    },
    moveUpTree () {
     //当前选中行
      console.log("currentRow", this.currentRow);
      if (this.currentRow.index == 1) {
        //根节点
        return;
      }
      if (!!this.currentRow.index) {
        const { index } = this.currentRow;
        console.log("currentRow", this.currentRow);
        let indexarr = index.split(".");
        if (indexarr[indexarr.length - 1] == "1") {
          // 判断是否是同级第一个
          this.$message("已是同级第一行无法上移");
        } else {
          let selectrow, tragetrow;
          if (!!this.currentRow.index) {
            selectrow = this.currentRow.index.split(".");
            tragetrow = selectrow.slice(0);
            tragetrow[tragetrow.length - 1] = (
              parseInt(tragetrow[tragetrow.length - 1]) - 1
            ).toString();
          }
          let selectStr = this.getTreeIndex(selectrow); // 获取树节点路径 字符
          let targetStr = this.getTreeIndex(tragetrow);
          let selectChild = selectStr.substring(0, selectStr.lastIndexOf("[")); // 字符数组
          let targetChild = targetStr.substring(0, targetStr.lastIndexOf("["));
          console.log(eval(targetStr), eval(targetChild));
          let obj = eval(selectStr);
          this.$set(
            eval(selectChild),
            parseInt(selectrow[selectrow.length - 1]) - 1,
            eval(targetStr)
          );
          this.$set(
            eval(targetChild),
            parseInt(tragetrow[tragetrow.length - 1]) - 1,
            eval(obj)
          );
          this.setTableIndex(this.list);
        }
      } else {
        this.$message("请选中一行");
      }
    },