43 带 fixed 列的 el-table 不兼容于 sortablejs

前言

这是一个基于 sortablejs 来实现的 el-table 的拖拽功能的基础实现 

然后 这个过程中遇到的一个比较特殊的问题是, 关于 el-table-column 的 fixed 的属性, 对于 sortablejs 这边来定位目标选择列 影响的一个问题 

在基础的用例中, 使用 “.el-table__body-wrapper tbody” 去定位目标元素, 然后 带 class 为 draggableClass 的元素作为可以拖拽的元素, 来实现 拖拽的交互

 

 

基础的拖拽的实现

测试用例如下 

<template>
  <div class="testParent">

    <el-table :data="weekPlan" row-key="id">
      <el-table-column label="id" prop="id" ></el-table-column>
      <el-table-column label="星期" prop="name" ></el-table-column>
      <el-table-column label="移动" >
        <div class="draggableClass" style="width:20px; height:20px; background-color: blue; cursor:move;" ></div>
      </el-table-column>
<!--      <el-table-column label="移动fixedLeft" :fixed="'left'" >-->
<!--        <div class="draggableClass" style="width:20px; height:20px; background-color: blue; cursor:move;" ></div>-->
<!--      </el-table-column>-->
<!--      <el-table-column label="移动fixedRight" :fixed="'right'" >-->
<!--        <div class="draggableClass" style="width:20px; height:20px; background-color: blue; cursor:move;" ></div>-->
<!--      </el-table-column>-->
    </el-table>

  </div>

</template>

<script>

  import Sortable from "sortablejs"

  export default {
    name: "HelloTableSortable",
    data() {
      return {
        weekPlan: [
          {
            id: "01",
            name: "monday",
            sort: 10,
          },
          {
            id: "02",
            name: "tuesday",
            sort: 22,
          },
          {
            id: "03",
            name: "wednesday",
            sort: 12,
          }
        ],
      }
    },
    computed: {},
    mounted() {
      this.$nextTick(() => {
        setTimeout(this.handleSortable, 100)
      })

      // sort demo
      this.weekPlan.sort((e1, e2) => e1.sort - e2.sort)
      console.log(this.weekPlan)
    },
    created() {
    },
    methods: {
      handleSortable() {
        let _this = this
        const tbody = document.querySelector(".el-table__body-wrapper tbody")
        Sortable.create(tbody, {
          handle: ".draggableClass",
          animation: 350,
          easing: 'cubic-bezier(0.34,1.56,0.64,1)',
          onEnd: ({newIndex, oldIndex}) => {
            let isMoveUp = newIndex < oldIndex
            let oldEntry = _this.weekPlan[oldIndex]
            // 2 -> 0
            if(isMoveUp) {
              for(let i=oldIndex; i>newIndex; i--) {
                _this.weekPlan[i] = _this.weekPlan[i-1]
              }
              // 0 -> 2
            } else {
              for(let i=oldIndex; i<newIndex; i++) {
                _this.weekPlan[i] = _this.weekPlan[i+1]
              }
            }
            _this.weekPlan[newIndex] = oldEntry
            console.log(_this.weekPlan.map(e => e.id))
          }
        })
      }
    },
  }
</script>

<style>

</style>

 

效果如下, console 里面打印的是 拖拽结束之后的一个最新的顺序 

具体的记录的 sort, 就是该元素的索引 

a897bdd3e7e948cf803d6d8ae622cf4b.png

 

从 dom 结构来看, 是一个单纯的一个 table, 然后下面是 th, 各个 tr 

然后 我们业务代码中基于 “.el-table__body-wrapper tbody . draggableClass” 可以正常的定位到目标拖拽元素 

ee0d9832ca7149c386295b6697a1751c.png

 

 

目标拖拽元素在 带fixed的 el-table-column 上面的异常情况 

基于上面的测试用例, 注释掉 “移动” 列, 解除注释 “移动fixedLeft”, “移动fixedRight” 列 

然后 这时候 你可以发现, 拖动 这两列 都不行了, 不管是拖拽 “移动fixedLeft”列, 还是 “移动fixedRight”列 

这个时候 页面 dom 结构如下

可以看到这时候 dom 树上面有三个 table, 一个在 el-table 下面, 一个在 el-table 下面的 el-table__fixed 下面, 一个在 el-table 下面的 el-table__fixed-right 下面 

el-table 下面的 el-table__fixed 下面 table, 主要是这部分配置了 fixed=’left‘ 的 el-table-column 的展示交互 

el-table 下面的 el-table__fixed-right 下面 table, 主要是这部分配置了 fixed=’right‘ 的 el-table-column 的展示交互 

d34cb08dd6f94197b7b5ff48dfd08964.png

 

页面上 “移动fixedRight“ 选择列右键查看元素, 可以看到 在最上层的元素是 使用的是包含在 el-table 下面的 el-table__fixed-right 下面 table 下面的元素 

b529f13797024e8899d883156fc33a0a.png

 

页面上 “移动fixedLeft“ 选择列右键查看元素, 可以看到 在最上层的元素是 使用的是包含在 el-table 下面的 el-table__fixed 下面 table 下面的元素 

4d9b16096ec1428ca2e3ab94a39c6403.png

 

页面上 数据中间列 选择列右键查看元素, 可以看到 在最上层的元素是 使用的是包含在 el-table 下面的 el-table__fixed 下面 table 下面的元素 

f1cbe16ef8524f62bd2622514916fcf2.png

 

然后 我们业务代码中拿到的元素是 数据中间列  

然后 它下面的 draggableClass 的元素在页面上, 不是 z-index 在最上面的元素, 页面的点击, 拖拽等等事件 选中的不是该元素 

const tbody = document.querySelector(".el-table__body-wrapper tbody")

 

所以 需要更新 Sortable.create 的时候选择的元素 

假设我们需要拖拽 “移动fixedRight” 的元素, 则我们更新 tbody 的 selector 如下 

const tbody = document.querySelector(".el-table__fixed-right tbody")

 

 

但是这样会存在一个问题就是, 因为 fixedLeft列 和 数据中间列 和 fixedRight列 是分开的, 然后 我这里将 fixedRight列 的 第二行 和 第一行 交换了位置

但是 fixedLeft列 和 数据中间列 的第二行 和 第一行 是没有交换位置的

这时候 就造成了数据的错位

545b0740b9d549baa3d616ce6d5b5a39.png

 

如下就使 拖拽中, 拖拽之后 的截图, 可以看到的是 第二行的 fixedLeft列 和 数据中间列 的 第二行 和 第一行 是没有交换位置的

造成了数据的展示错误 

47deea1afacd45778f75e0de77e13687.png

71b1243a3680454eb0282752cef55f30.png

 

所以再这种 el-table 中基于 sortablejs 来实现拖拽的场景下面 

需要尽量避免使用 fixed=”left”, fixed=”right” 的配置, 否则 可能会造成一些 奇怪的问题

 

 

完 

 

 

 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-28 00:28:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-28 00:28:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-28 00:28:03       82 阅读
  4. Python语言-面向对象

    2024-03-28 00:28:03       91 阅读

热门阅读

  1. vue中数字转汉字,带小数转化

    2024-03-28 00:28:03       39 阅读
  2. 利用Cas中service重定向钓鱼网站问题

    2024-03-28 00:28:03       47 阅读
  3. 【机器学习】如何计算解释模型的SHAP值

    2024-03-28 00:28:03       41 阅读
  4. 华为机试真题练习汇总(101~110)

    2024-03-28 00:28:03       37 阅读
  5. 新建uni-modules插件

    2024-03-28 00:28:03       39 阅读
  6. 前端理论总结(js)——闭包和内存泄漏

    2024-03-28 00:28:03       42 阅读
  7. 关于远程调试应用中的网页鸿蒙

    2024-03-28 00:28:03       38 阅读
  8. 面试算法-118-用队列实现栈

    2024-03-28 00:28:03       40 阅读
  9. [c++] 自写 MyString 类

    2024-03-28 00:28:03       35 阅读