vue3+element-plus实现table表格整列的拖拽

参考文章: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保持一致

相关推荐
持续前行6 小时前
vscode 中找settings.json 配置
前端·javascript·vue.js
JosieBook6 小时前
【Vue】11 Vue技术——Vue 中的事件处理详解
前端·javascript·vue.js
安逸点7 小时前
Vue项目中使用xlsx库解析Excel文件
vue.js
一只小阿乐7 小时前
vue 改变查询参数的值
前端·javascript·vue.js·路由·router·网文·未花中文网
小酒星小杜8 小时前
在AI时代下,技术人应该学会构建自己的反Demo地狱系统
前端·vue.js·ai编程
Code知行合壹8 小时前
Pinia入门
vue.js
今天也要晒太阳4738 小时前
element表单和vxe表单联动校验的实现
vue.js
依赖_赖9 小时前
前端实现token无感刷新
前端·javascript·vue.js
hhcccchh10 小时前
学习vue第十三天 Vue3组件深入指南:组件的艺术与科学
javascript·vue.js·学习
zhengxianyi51510 小时前
ruoyi-vue-pro本地环境搭建(超级详细,带异常处理)
前端·vue.js·前后端分离·ruoyi-vue-pro