Bootstrap

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

  • 原因 由于我的表头是由数组循环遍历生成的,而选择列不在数组内,只能在循环外定义el-table-column,造成拖动时索引错乱
  • 错误代码
  <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 写到循环体内
  <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" 表示除了选择列之外都可以拖动
  <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>
//拖拽列
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方法
  <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>
//解决向选择列拖动的bug
 function tableRowClassName(row) {
      if (row.columnIndex == 0) {
        return "filtered";
      }
      return "";
    }
//拖拽列
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;
      }
    })
}

完整代码

  <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>
//拖拽列
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

;