参考文章:https://blog.csdn.net/candy0521/article/details/136470284
一、为防止原文章不见了将参考文章代码拷过来了(不好意思):这是参考文章的代码 可直接复制粘贴运行
<template>
<div class="draggable-table">
<el-table ref="tableRef"
:data="tableData.data"
:key="'table'+tableData.key"
@header-dragend="handleHeaderDragend"
border
style="width: 100%">
<template v-for="item of tableData.columnList">
<el-table-column show-overflow-tooltip :prop="item.prop" :label="item.label"
:width="item.width"></el-table-column>
</template>
</el-table>
</div>
</template>
<script lang="ts" setup>
import {nextTick, onMounted, reactive, ref} from "vue";
import Sortable from 'sortablejs';
const tableData = reactive({
key: new Date().getTime(),
data: [
{
id: 'id',
name: 'name',
amount1: 'amount1',
amount2: 'amount2',
amount3: 'amount3',
},
{
id: '12987123',
name: 'Tom',
amount1: '165',
amount2: '4.43',
amount3: 12,
},
{
id: '12987124',
name: 'Tom',
amount1: '324',
amount2: '1.9',
amount3: 9,
},
{
id: '12987125',
name: 'Tom',
amount1: '621',
amount2: '2.2',
amount3: 17,
},
{
id: '12987126',
name: 'Tom',
amount1: '539',
amount2: '4.1',
amount3: 15,
},
],
columnList: [
{
label: 'ID',
prop: "id",
width: "180"
},
{
label: 'Name',
prop: "name",
width: "180"
},
{
label: 'Amount1',
prop: "amount1",
width: "180"
},
{
label: 'Amount2',
prop: "amount2",
width: "180"
},
{
label: 'Amount3',
prop: "amount3",
width: "180"
},
]
})
const tableRef = ref();
let sortable:Sortable;
onMounted(() => {
initTableHeaderDrag(); // 初始化拖拽事件
})
function initTableHeaderDrag(){
if(sortable){
sortable.destroy();
}
let el = tableRef.value.$el.querySelector('.el-table__header-wrapper tr')
sortable = Sortable.create(el, {
animation: 150,
onEnd(evt: any) {
const oldItem = tableData.columnList[evt.oldIndex];
tableData.columnList.splice(evt.oldIndex, 1);
tableData.columnList.splice(evt.newIndex, 0, oldItem);
tableData.key = new Date().getTime(); // 变更key,强制重绘table。如果不强制变更的话,会出现一些奇奇怪怪的问题,列宽度调整也会出现问题
nextTick(() => {
initTableHeaderDrag(); // 因为table被强制重新绘制,因此需要重新监听
})
}
})
}
function handleHeaderDragend(newWidth, oldWidth, column, event){
for(let item of tableData.columnList){
if(item.label == column.label){
item.width = newWidth;
}
}
initTableHeaderDrag(); // 重新注册,防止变更宽度后无法拖动
}
</script>
<style scoped lang="scss">
</style>
注意: 整列的拖拽一定是 let el = tableRef.value.$el.querySelector('.el-table__header-wrapper tr')
有些参考选择器的内容是body
二、以下是项目需求在以上代码的基础上修改
1、列表可以根据复选框的值动态显示表格里面显示隐藏的数据
2、实现的主要代码
1、安装import Sortable from 'sortablejs';
2、onMounted(()=>{
init() //这个方法是请求接口获取到表格(tabelData.data)的数据
nextTick(() => {
initTableHeaderDrag(); // 初始化拖拽事件
})
})
3、const init = async() => {
const res =await getTableData()
tableData.data = res.data
}
4、复选框的数据
//这个按钮是控制el-drawer的弹出
<img width="28px" src="@/assets/icon/selection.png" @click="drawer = true" />
//这是复选框的弹窗 可直接参考element-plus组件的内容
<el-drawer v-model="drawer" title="列表显示设置" :direction="direction" :before-close="handleClose">
<el-checkbox-group v-model="checkList" @change="checkboxChange" v-for="item in checkBoxData"
:key="item.value">
<el-checkbox :label="item.label" :value="item.label"></el-checkbox>
</el-checkbox-group>
</el-drawer>
//复选框默认显示的数据
const checkList = ref(["物料编码", "产品类别", "编码有效期", "编码状态", "供货状态", "申请人", "申请日期", "流程环节"])
//tableData 数据
const tableData = reactive({
key: new Date().getTime(),
data: [],
//这里是表格首次默认展示的数据,如果没有序号也可以直接赋值使用checkBoxData 的数据
columnList: [
//这里比checkBoxData 多了一个序号
{
label: '序号',
prop: "",
width: "60"
},
{
label: '物料编码',
prop: "imaterialCoded",
width: "180"
},
...
]
})
//复选框发生变化
const checkboxChange = () => {
const arr = checkBoxData.filter((item) => { return checkList.value.some((i) => { return i == item.label }) })
tableData.columnList = arr //修改显示的列
}
const checkBoxData = reactive([
{
label: '物料编码',
prop: "imaterialCoded",
width: "180"
},
{
label: '项目编码',
prop: "projectCode",
width: "180"
},
... //其他省略了
])
5、表格特殊数据的处理
<el-table-column show-overflow-tooltip :prop="item.prop" :label="item.label" :width="item.width">
<template #default="scope">
<span v-if="item.label == '序号'" style="text-align:center;width:100%;display:inline-block">
{{ scope.$index+1 }}
</span>
<span v-if="item.label == '物料编码'">
<a style="color: #1890ff; text-decoration: underline;cursor:pointer" @click="getInfo(scope.row.id)">{{ scope.row.materialCode }}
</a>
</span>
<span v-else-if="item.label == '产品类别'">
{{ scope.row.productType == 1 ? '标准件' : '定制件' }}
</span>
...
<span v-else>{{ scope.row[item.prop] }}</span>
</template>
</el-table-column>
注意:tableData.columnList 可以设置默认值,不能设置为空,且复选框的数据格式(checkBoxData )要与columnList保持一致