用vue和sortableJS轻松实现表格拖拽排序

前言

表格是数据展示中常用的形式之一,而拖动排序功能则可以提高用户操作效率。本文将介绍如何使用 vuesortableJS 实现表格拖动排序,让数据展示更加灵活和高效。


安装

npm install sortablejs --save
cnpm install sortablejs --save

引入

import Sortable from 'sortablejs'

使用

el-table 中必须加上 row-key="id",否则可能会导致排序不成功。原因是因为 vue 的加载循环机制,在进行删除时,一定要添加 key,跟使用 v-for 循环一样都需要添加绑定 key 值。

基础表格拖动排序

在这里插入图片描述


源码如下

<template>
  <div>
    <!-- 表格控件 -->
    <el-table :data="tableData" ref="tableNode" border highlight-current-row row-key="id">
      <el-table-column prop="name" label="姓名" align="center"></el-table-column>
      <el-table-column prop="sex" label="性别" align="center"></el-table-column>
      <el-table-column prop="age" label="年龄" align="center"></el-table-column>
      <el-table-column prop="address" label="地址" align="center"></el-table-column>
    </el-table>
  </div>
</template>

<script>
import Sortable from "sortablejs"; //引入下载的插件
export default {
  data() {
    return {
      // 模拟数据
      tableData: [
        {
          id: "1",
          name: "第一",
          sex: "男",
          age: "12",
          address: "北京",
        },
        {
          id: "2",
          name: "第二",
          sex: "男",
          age: "23",
          address: "上海",
        },
        {
          id: "3",
          name: "第三",
          sex: "女",
          age: "21",
          address: "广州",
        },
        {
          id: "4",
          name: "第四",
          sex: "女",
          age: "12",
          address: "深圳",
        },
      ],
    };
  },
  mounted() {
    this.pullSort(); //声明表格拖动排序方法
  },
  methods: {
    //表格拖动排序方法
    pullSort() {
      // 通过ref获取Dom节点
      const el = this.$refs.tableNode.$el.querySelectorAll(
        ".el-table__body-wrapper > table > tbody"
      )[0];
      this.sortable = Sortable.create(el, {
        animation: 600, //拖拽动画(毫秒)
        setData: function (dataTransfer) {
          dataTransfer.setData("Text", "");
        },
        // 结束拖拽
        onEnd: (e) => {
          //e.oldIndex为拖动一行原来的位置;e.newIndex为拖动后新的位置
          const oldRow = this.tableData[e.oldIndex]; // 移动元素集合
          const newRow = this.tableData[e.newIndex]; // 新的元素集合
          console.log(oldRow, "移动元素集合");
          console.log(newRow, "新的元素集合");
          // 调用接口传参即可
        },
      });
    },
  },
};
</script>

树形结构表格拖动排序

在这里插入图片描述


树形表格拖动不同于简单的表格拖动,我们要考虑到树形表格每一层的层级,如果返回的数据没有层级,我们需要给树形的数据去添加每一层的层级,其次,我们还得将树形表格数据转化为平铺数据在进行拖动,如果不转换的话,后面拖动的位置就是不对的,就会出错了,下面看代码实例。

源码如下

<template>
  <div>
    <!-- 表格树控件 -->
    <el-table :data="tableData" ref="tableNode" border highlight-current-row row-key="id">
      <el-table-column prop="label" label="模块" align="center"></el-table-column>
    </el-table>
  </div>
</template>

<script>
import Sortable from "sortablejs"; //引入下载的插件
// import { treeSort } from "@/api/system";//引入接口方法
export default {
  data() {
    return {
      // 模拟数据,实际情况根据后台返回数据调整
      tableData: [
        {
          id: "2619",
          label: "菜单一",
          parentId: "79f32a6fdbaisdaishdadhsd0b3540e17a0a",
        },
        {
          id: "4d1dd2a5wd3s2f1a5fd1as8f6869dc7b",
          label: "菜单二",
          parentId: "79f32a6fdbaisdaishdadhsd0b3540e17a0a",
          children: [
            {
              id: "4006",
              label: "A-1",
              parentId: "4d1dd2a5wd3s2f1a5fd1as8f6869dc7b",
            },
          ],
        },
        {
          id: "52cqw8r7f4a65s3d1a5f4s65a3d2w1507f93",
          label: "菜单三",
          parentId: "79f32a6fdbaisdaishdadhsd0b3540e17a0a",
          children: [
            {
              id: "4005",
              label: "B-1",
              parentId: "52cqw8r7f4a65s3d1a5f4s65a3d2w1507f93",
            },
          ],
        },
        {
          id: "66d5a4s13d2c1as5f4a6w5s13das12a89",
          label: "菜单四",
          parentId: "79f32a6fdbaisdaishdadhsd0b3540e17a0a",
          children: [
            {
              id: "3033",
              label: "C-1",
              parentId: "66d5a4s13d2c1as5f4a6w5s13das12a89",
            },
            {
              id: "3034",
              label: "C-2",
              parentId: "66d5a4s13d2c1as5f4a6w5s13das12a89",
            },
          ],
        },  
      ],
      activeRows: [], // 转换为列表的数据
    };
  },
  mounted() {
    this.pullSort(); //声明表格拖动排序方法
  },
  methods: {
    //拖拽排序
    pullSort() {
      const tbody = this.$refs.tableNode.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0];
      const _this = this;//防止this指向问题
      Sortable.create(tbody, {
        animation: 600,
        onMove({ dragged, related }) {
          _this.$set(_this,"tableData",_this.arrayTreeSetLevel(_this.tableData)); // 树形结构数据添加level
          _this.activeRows = _this.treeToTile(_this.tableData); // 把树形的结构转为列表再进行拖拽
        },
        onEnd(e) {
          //e.oldIndex为拖动一行原来的位置,e.newIndex为拖动后新的位置
          if (e.oldIndex !== e.newIndex) {
            const oldRow = _this.activeRows[e.oldIndex]; // 移动元素
            const newRow = _this.activeRows[e.newIndex]; // 新的元素
            // level 当前层级  parentId 父级id
            if (oldRow.level != newRow.level || oldRow.parentId != newRow.parentId) {
              //不能跨级拖拽
              _this.$message({
                message: "只允许同级拖拽",
                type: "warning",
              });
              _this.tableData = [];//清空列表数据
              // _this.getTableTree();//调用列表接口
              return false;
            } else {
              // // 接口参数
              // let data = {
              //   previousId: oldRow.id,
              //   lastId: newRow.id,
              // };
              // // 请求接口
              // treeSort(data).then((res) => {
              //   if (res.code == "10000") {
              //     _this.tableData = [];//清空列表数据
              //     _this.getTableTree();//调用列表接口
              //     _this.$message({
              //       message: res.msg,
              //       type: "success",
              //     });
              //   }
              // });
            }
          }
        },
      });
    },
    // 给树形的数据去添加每一层的层级
    arrayTreeSetLevel(array, levelName = "level", childrenName = "children") {
      if (!Array.isArray(array)) {
        return [];
      }
      const recursive = (array, level = 0) => {
        level++;
        return array.map((v) => {
          v[levelName] = level;
          const child = v[childrenName];
          if (child && child.length) {
            recursive(child, level);
          }
          return v;
        });
      };
      return recursive(array);
    },
    // 将树数据转化为平铺数据
    treeToTile(treeData, childKey = "children") {
      const arr = [];
      const expanded = (data) => {
        if (data && data.length > 0) {
          data
            .filter((d) => d)
            .forEach((e) => {
              arr.push(e);
              expanded(e[childKey] || []);
            });
        }
      };
      expanded(treeData);
      return arr;
    },
  },
};
</script>

总结

SortableJS 为开发者提供了多种拖动效果,单列表、多列表、嵌套排序等等都不在话下,大家感兴趣的话可以去官网查看: SortableJS 中文网


相关推荐

vue+element实现树形上下拖拽,快速提升你的前端技能
教你一招,element表格行轻松上下移动

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水星记_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值