解决Sortable拖动el-table表头时,由于选择列造成的拖拽顺序错乱的bug

  • 原因 由于我的表头是由数组循环遍历生成的,而选择列不在数组内,只能在循环外定义el-table-column,造成拖动时索引错乱
  • 错误代码
javascript 复制代码
  <el-table
    @header-dragend="headerDragend"
    id="out-table"
    :data="state.sliceTable"
    border
    stripe
    ref="TableRef"
    :row-key="getRowKeys(pageData)"
  >
  <el-table-column type="selection" width="55" fixed /> 
>
    <template v-for="(item, index) in state.pageDataTitle" :key="index"> 
      <el-table-column
        :prop="item.value"
        :label="item.name"
        :key="index"
      >
        <template #default="scope">
          <slot :name="item.value" :scope="scope">{{ scope.row[item.value] }}</slot>
        </template>
      </el-table-column>
    </template>
  </el-table>
  • 解决办法 向数组开头push一条 type="selection" 的对象 并把el-table-column 写到循环体内
javascript 复制代码
  <template v-for="(item, index) in state.pageDataTitle" :key="index">
    <el-table-column type="selection" v-if="item.type" width="55" fixed />
    <el-table-column
      :prop="item.value"
      :label="item.name"
      :key="index"
    >
      <template #default="scope">
        <slot :name="item.value" :scope="scope">{{ scope.row[item.value] }}</slot>
      </template>
    </el-table-column>
  </template>
  • 当拖动选择列 或 拖向选择列时 仍然会造成拖动顺序混乱 所以我们要禁止掉
  • 给el-table-column添加 class-name="allowdrag" 表示除了选择列之外都可以拖动
javascript 复制代码
  <el-table-column
    class-name="allowdrag"
    :label="item.name"
    :key="index"
  >
    <template #default="scope">
      <slot :name="item.value" :scope="scope">{{ scope.row[item.value] }}</slot>
    </template>
  </el-table-column>
javascript 复制代码
//拖拽列
const columnDrop2 = (dom) => {
  if (!dom) return
  Sortable.create(dom.$el.querySelector('.el-table__header-wrapper>.el-table__header tr'), {
    handle: '.allowdrag',  //除了选择列都可以选择
    onEnd: (sortableEvent) => {
      const targetThElem = sortableEvent.item;
      const wrapperElem = targetThElem.parentNode;
      const newIndex = sortableEvent.newIndex;
      const oldIndex = sortableEvent.oldIndex;
      const oldTrElement = wrapperElem.children[oldIndex];
      const currRow = state.pageDataTitle?.splice(oldIndex, 1)[0];
      state.pageDataTitle?.splice(newIndex, 0, currRow);
      if (newIndex > oldIndex) {
        wrapperElem.insertBefore(targetThElem, oldTrElement)
      } else {
        wrapperElem.insertBefore(
          targetThElem,
          oldTrElement ? oldTrElement.nextElementSibling : oldTrElement
        )
      }

    },
  })
}
  • 这样解决了选择列向其他列拖动 ,但没有解决其他列向选择列拖动
  • 解决办法 添加 :header-cell-class-name="tableRowClassName" 并添加onMove方法
javascript 复制代码
  <el-table
    :header-cell-class-name="tableRowClassName"
    id="out-table"
    :data="state.sliceTable"
    ref="TableRef"
  >
    <template v-for="(item, index) in state.pageDataTitle" :key="index">
      <el-table-column type="selection" v-if="item.type" width="55" fixed />
      <el-table-column
        class-name="allowdrag"
        :prop="item.value"
        :label="item.name"
        :key="index"
      >
        <template #default="scope">
          <slot :name="item.value" :scope="scope">{{ scope.row[item.value] }}</slot>
        </template>
      </el-table-column>
    </template>
  </el-table>
javascript 复制代码
//解决向选择列拖动的bug
 function tableRowClassName(row) {
      if (row.columnIndex == 0) {
        return "filtered";
      }
      return "";
    }
javascript 复制代码
//拖拽列
const columnDrop2 = (dom) => {
    if (!dom) return
    Sortable.create(dom.$el.querySelector('.el-table__header-wrapper>.el-table__header tr'), {
        handle: '.allowdrag',
        onEnd: (sortableEvent) => {
            const targetThElem = sortableEvent.item;
            const wrapperElem = targetThElem.parentNode;
            const newIndex = sortableEvent.newIndex;
            const oldIndex = sortableEvent.oldIndex;
            const oldTrElement = wrapperElem.children[oldIndex];
            const currRow = state.pageDataTitle?.splice(oldIndex, 1)[0];
           state.pageDataTitle?.splice(newIndex, 0, currRow)
            if (newIndex > oldIndex) {
                wrapperElem.insertBefore(targetThElem, oldTrElement)
            } else {
                wrapperElem.insertBefore(
                    targetThElem,
                    oldTrElement ? oldTrElement.nextElementSibling : oldTrElement
                )
            }

        },
        //解决向选择列拖动的bug
        onMove(e) {
        return e.related.className.indexOf("filtered") === -1;
      }
    })
}

完整代码

javascript 复制代码
  <el-table
    :header-cell-class-name="tableRowClassName"
    id="out-table"
    :data="state.sliceTable"
    ref="TableRef"
  >
    <template v-for="(item, index) in state.pageDataTitle" :key="index">
      <el-table-column type="selection" v-if="item.type" width="55" fixed />
      <el-table-column
        class-name="allowdrag"
        :prop="item.value"
        :label="item.name"
        :key="index"
      >
        <template #default="scope">
          <slot :name="item.value" :scope="scope">{{ scope.row[item.value] }}</slot>
        </template>
      </el-table-column>
    </template>
  </el-table>
javascript 复制代码
//拖拽列
const columnDrop2 = (dom) => {
    if (!dom) return
    Sortable.create(dom.$el.querySelector('.el-table__header-wrapper>.el-table__header tr'), {
        handle: '.allowdrag',
        onEnd: (sortableEvent) => {
            const targetThElem = sortableEvent.item;
            const wrapperElem = targetThElem.parentNode;
            const newIndex = sortableEvent.newIndex;
            const oldIndex = sortableEvent.oldIndex;
            const oldTrElement = wrapperElem.children[oldIndex];
            const currRow = state.pageDataTitle?.splice(oldIndex, 1)[0];
           state.pageDataTitle?.splice(newIndex, 0, currRow)
            if (newIndex > oldIndex) {
                wrapperElem.insertBefore(targetThElem, oldTrElement)
            } else {
                wrapperElem.insertBefore(
                    targetThElem,
                    oldTrElement ? oldTrElement.nextElementSibling : oldTrElement
                )
            }

        },
        //解决向选择列拖动的bug
        onMove(e) {
        return e.related.className.indexOf("filtered") === -1;
      }
    })
}

//解决向选择列拖动的bug
 function tableRowClassName(row) {
      if (row.columnIndex == 0) {
        return "filtered";
      }
      return "";
    }

效果图

QQ录屏20231211155823

相关推荐
一 乐1 小时前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
BillKu2 小时前
Vue3 + TypeScript + Element Plus 表格行按钮不触发 row-click 事件、不触发勾选行,只执行按钮的 click 事件
vue.js·elementui·typescript
小前端大牛马2 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js
萌萌哒草头将军4 小时前
🚀🚀🚀VSCode 发布 1.101 版本,Copilot 更全能!
前端·vue.js·react.js
摇摇奶昔x6 小时前
Vue.js 中 “require is not defined“
前端·javascript·vue.js
sunbyte7 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | RandomChoicePicker(标签生成)
前端·javascript·vue.js
z_y_j2299704388 小时前
vue前端项目打包和部署
前端·javascript·vue.js
lbchenxy8 小时前
antd vue a-range-picker如何设置不能选择当前和之后的时间,包含时分秒
前端·javascript·vue.js
前端小白从0开始8 小时前
前端基础知识ES6系列 - 01(var、let、const之间的区别)
前端·javascript·vue.js·es6
前端呆猿10 小时前
Vuex:Vue.js 应用程序的状态管理模式
android·vue.js·flutter