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保持一致

相关推荐
Violet_YSWY1 天前
讲一下ruoyi-vue3的前端项目目录结构
前端·javascript·vue.js
C_心欲无痕1 天前
vue3 - toRaw获取响应式对象(如由reactive创建的)的原始对象
前端·javascript·vue.js
老华带你飞1 天前
学生宿舍管理|基于java + vue学生宿舍管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
OpenTiny社区1 天前
2025年OpenTiny年度人气贡献者评选正式开始
前端·javascript·vue.js
JosieBook1 天前
【Vue】04 Vue技术——Vue 模板语法详解:插值与指令
前端·javascript·vue.js
BD_Marathon1 天前
Router_编程式路由
vue.js
Mr.app1 天前
Vue3 + TS 动态路由系统实现总结
vue.js
贺今宵1 天前
el-table-v2element plus+大量数据展示虚拟表格实现自定义排序,选择样式调整行高亮
javascript·vue.js·ecmascript
计算机程序设计小李同学1 天前
基于 Spring Boot 和 Vue.js 技术栈的网上订餐系统
vue.js·spring boot·后端
毕设十刻1 天前
基于Vue的家教预约系统7fisz(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js