表格数据拖拽排序 sortable.js

发布时间 2023-11-14 14:09:50作者: shayloyuki

需求

拖拽表格的行数据,实现排序。

问题

拖拽后调用接口,但视图没变,还是原来的顺序

场景:拖拽表格行数据后,tableDataArr 中数据的 orderNum 值会改变,实现拖拽换序。

期望情况:页面根据更改后的 orderNum 重新排序。

实际情况:接口数据变了,但是页面行数据没有改变。也就是说,页面没有实现响应式更新。

尝试1:使用 $set 赋值,无效。

	// 旧代码:
      this.tableDataArr = arr.slice(
        (this.pageNum - 1) * this.pageSize,
        this.pageNum * this.pageSize
      );
	// 新代码:无效
      this.$set(this, 'tableDataArr', arr.slice(
        (this.pageNum - 1) * this.pageSize,
        this.pageNum * this.pageSize
      ))

尝试2:赋值后使用 this.$forceUpdate() 强制更新,无效

尝试3:使用 splice() 赋值

      const newArr =  arr.slice((this.pageNum - 1) * this.pageSize,this.pageNum * this.pageSize)
      this.tableList.splice(
        0,
        this.tableList.length,
        ...newArr
      );

解决:赋值前先重置数组

      // 重置 tableList,避免换序不更新页面
      this.tableList = [];
	  // 赋值
      this.tableDataArr = arr.slice(
        (this.pageNum - 1) * this.pageSize,
        this.pageNum * this.pageSize
      );

原因

sortable.js 拖拽排序是插入,即把A插入到B之前或之后。拖拽(页面数据顺序改变了但数组没变)后,再调用换序接口,获得的数组变了,但没有引起视图的变化。

这是因为 Vue 无法监听数组顺序的改变。

拖拽方向不同,导致被替换行不同(测试需从不同拖拽方向测试)

  • 拖拽行 A
  • 插入行 B
  • 被替换行

备注:oldIndex 指的是 A 原来的位置,newIndex 指的是 A 拖拽后的位置。

情况一:oldIndex < newIndex

  • A 拖到B 后面,A 取代了 B 原来的位置;
  • A 拖到B 前面,A 取代了 B 前一个属性,即C 原来的位置;

image

情况二:oldIndex > newIndex

  • A 拖到B 后面,A 取代了 B 后一个属性,即C 原来的位置;
  • A 拖到B 前面,A 取代了 B 原来的位置;

image

如何修改放置行的背景色

ghostClass属性:颜色名。若为空字符串表示无颜色。

image

如何限制可拖拽的区域、可放置区域

filter 属性:可拖拽的元素
image

onMove 限制可放置区域
image

      Sortable.create(tbody, {
        filter: ".common-row", // 继承属性不可拖拽
	……
        // 不允许拖拽到继承属性区域中
        onMove(e) {
          return e.related.className.indexOf("common-row") === -1;
        },
      });

参考链接:

  1. vue2.0中给对象或者数组重新赋值并且保证响应式
  2. 数组的侦听
  3. sortable.js配置项