Vue3 el-table 使用useSortable 完成表格拖拽排序功能

2,000 阅读1分钟

表格拖拽排序是一个常见功能

查看效果

2023-07-24 07.40.00.gif

准备

加载依赖

我们使用第三方sortablejs来实现

import Sortablejs from "sortablejs";

定义类型

export interface Sortable {
  drag?: boolean;
  onDrag?: (drag: Drag) => void;
}

增加props

  sortable: {
    type: Object as PropType<Sortable>,
    default: () => ({}),
  },

useSortable实现

function useSortable(
  sortable: Sortable,
  elProTable: Ref,
  dataSource: Ref<Data[]>
) {
  const drag = sortable.drag;
  const onDrag = sortable.onDrag;

  drag &&
    onMounted(() => {
      const tbody = elProTable?.value?.querySelector(
        ".el-table__body-wrapper tbody"
      );
      const sortable =
        tbody &&
        Sortablejs.create(tbody, {
          handle: ".sortable-handle", // Restricts sort start click/touch to the specified element
          ghostClass: "sortable-ghost", // Class name for the drop placeholder,
          setData: function (dataTransfer: any) {
            // to avoid Firefox bug
            // Detail see : https://github.com/RubaXa/Sortable/issues/1012
            dataTransfer.setData("Text", "");
          },
          onEnd: (evt: any) => {
            const targetRow = dataSource.value.splice(evt.oldIndex, 1)[0];
            dataSource.value.splice(evt.newIndex, 0, targetRow);

            onDrag &&
              onDrag({
                oldIndex: evt.oldIndex,
                newIndex: evt.newIndex,
                dataSource: dataSource.value,
              });

            // for show the changes, you can delete in you code
            // const tempIndex = this.newList.splice(evt.oldIndex, 1)[0];
            // this.newList.splice(evt.newIndex, 0, tempIndex);
          },
        });
      onUnmounted(() => {
        sortable.destroy();
      });
    });

  const node = drag && (
    <ElTableColumn width="30" fixed>
      <ElIcon class="sortable-handle">
        <Menu />
      </ElIcon>
    </ElTableColumn>
  );

  return { node };
}

调用

<h2>支持拖拽</h2>
<el-pro-table :data="tableData" :sortable="{ drag: true }">
<el-table-column prop="date" label="Date" />
<el-table-column prop="name" label="Name" />
<el-table-column prop="name" label="Name" />
<el-table-column prop="state" label="State" />
<el-table-column prop="city" label="City" />
<el-table-column prop="address" label="Address" width="600" />
<el-table-column prop="zip" label="Zip" />
<el-table-column label="Operations">
  <template #default="{ row }">
    <el-button link type="primary" size="small" @click="handleClick">
      编辑
    </el-button>
    <el-button v-if="row.status === 2" link type="primary" size="small">
      删除
    </el-button>
  </template>
</el-table-column>
</el-pro-table>