### 实现 Vue3 和 TypeScript 中 Element Plus 的 el-table 列拖拽功能
为了实现在 Vue3 和 TypeScript 环境下的 `el-table` 组件列拖拽功能,可以采用 Sortable.js 库来增强原生的表格交互能力。下面是一个详细的实现方案。
#### 安装依赖库
确保已经安装了必要的开发工具包:
```bash
npm install sortablejs element-plus vue@next --save
```
#### 创建自定义指令用于处理拖拽逻辑
创建一个新的文件夹 `/src/directives/` 并在此目录下新建一个名为 `drag-column.ts` 文件,在其中编写如下代码:
```typescript
// /src/directives/drag-column.ts
import { DirectiveBinding, nextTick } from 'vue';
import Sortable from 'sortablejs';
export default {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const options = Object.assign(
{},
{
animation: 180,
ghostClass: 'sortable-ghost',
onEnd({ newIndex, oldIndex }) {
let targetItem;
if (newIndex !== null && oldIndex !== null) {
const parentEl = el.closest('.el-table__body-wrapper');
const tableBodyRows =
parentEl?.querySelectorAll<HTMLElement>('.el-table__row') || [];
Array.from(tableBodyRows).forEach((tr, index) => {
tr.style.order = String(index);
if (index === newIndex) {
targetItem = tr.querySelector(`th:nth-child(${binding.value})`);
}
});
if (targetItem) {
setTimeout(() => {
targetItem.scrollIntoView({
block: 'center'
});
}, 0);
}
}
},
},
binding.arg || {}
);
new Sortable.default(el as any, options);
// 更新样式以适应新的顺序变化
nextTick().then(() => {
const ths = el.querySelectorAll('thead th');
[...ths].map((item, idx) =>
item.setAttribute('data-index', `${idx}`)
);
});
},
};
```
此部分实现了通过 SortableJS 对表头进行排序的功能,并且当发生位置改变时会触发相应的回调函数调整 DOM 结构[^1]。
#### 修改 Table 组件模板并应用自定义指令
编辑包含 `el-table` 的组件文件,比如命名为 `MyTableComponent.vue`, 添加以下内容:
```html
<!-- MyTableComponent.vue -->
<script lang="ts" setup>
import dragColumn from './directives/drag-column'; // 导入上面编写的自定义指令
</script>
<template>
<div class="table-container">
<el-table :data="tableData" style="width: 100%">
<!-- 使用 v-drag-column 自定义指令绑定每一列的数据索引 -->
<el-table-column prop="date" label="日期" width="180" />
<el-table-column
v-for="(col, i) in columns"
:key="i"
:prop="col.prop"
:label="col.label"
v-drag-column="{ arg: col.index + 1 }"
>
</el-table-column>
</el-table>
</div>
</template>
<style scoped>
.table-container {
/* 居中 */
margin: 100px auto;
width: 50%;
}
.sortable-ghost {
opacity: 0.7;
color: #fff !important;
background-color: rgba(255, 102, 102, 0.49) !important;
}
/* 设置表格间距等 */
.el-table {
margin: 10px 0;
}
</style>
```
这里的关键在于给每列表格头部加上了一个特殊的属性 `v-drag-column` 来启用拖拽行为,并传递当前列为参数以便后续操作[^4]。
#### 初始化数据源和其他配置
最后一步是在脚本区域初始化一些基础设置,例如加载初始数据显示在表格里以及监听事件更新状态等。
```javascript
const columns = ref([
{ prop: 'name', label: '姓名', index: 0 },
{ prop: 'address', label: '地址', index: 1 },
]);
const tableData = reactive([
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]);
```
这样就完成了一个简单的基于 Vue3、TypeScript 和 Element Plus 构建的支持列拖拽功能的表格实例[^3]。