element-plus 虚拟表格 table-v2 拖拽改变列宽功能(ps:网上搜不到的)

1,685 阅读1分钟

背景

element-plus 中,如果有大数据列表展示,我们通常会使用虚拟表格Virtualized Table实现,但是这个虚拟表格并不支持拖动改变列宽。本次我们就是要实现这个虚拟表格的拖动改变列宽的功能。

效果预览

image.png

image.png

思路

  1. 通过 headerCellRenderer 选项,添加一个1px的边,用于拖拽。
  2. 通过 ondragstartondragend 给这个边添加拖动事件,通过对比拖动前后的距离来进行改变当前列宽度

代码

复制到代码里就可以直接预览,注意: 用了less

<template>
  <el-table-v2 :columns="columns" :data="data" :width="700" :height="400" />
</template>

<script lang="jsx" setup>
import { ref } from "vue";

const dataGenerator = () => ({
  name: "张三",
  address: "上海市xxxx街道xxxx弄xxxx号",
  desc: "这是一个描述这是一个描述这是一个描述",
});

const columns = ref([
  {
    key: "name",
    dataKey: "name",
    align: "center",
    width: 150,
    headerCellRenderer: () => (
      <div
        class="header-box"
        ondragenter={(e) => e.preventDefault()}
        ondragover={(e) => e.preventDefault()}
      >
        <div>姓名</div>
        <div
          class="drag-line"
          draggable
          ondragstart={(e) => dragStart(e)}
          ondragend={(e) => dragEnd(e, "name")}
        ></div>
      </div>
    ),
    cellRenderer: ({ cellData: name }) => <div class="row">{name}</div>,
  },
  {
    key: "address",
    dataKey: "address",
    align: "center",
    width: 150,
    headerCellRenderer: () => (
      <div
        class="header-box"
        ondragenter={(e) => e.preventDefault()}
        ondragover={(e) => e.preventDefault()}
      >
        <div>家庭地址</div>
        <div
          class="drag-line"
          draggable
          ondragstart={(e) => dragStart(e)}
          ondragend={(e) => dragEnd(e, "address")}
        ></div>
      </div>
    ),
    cellRenderer: ({ cellData: address }) => <div class="row">{address}</div>,
  },
  {
    key: "desc",
    dataKey: "desc",
    width: 150,
    align: "center",
    headerCellRenderer: () => (
      <div
        class="header-box"
        ondragenter={(e) => e.preventDefault()}
        ondragover={(e) => e.preventDefault()}
      >
        <div>描述</div>
        <div
          class="drag-line"
          draggable
          ondragstart={(e) => dragStart(e)}
          ondragend={(e) => dragEnd(e, "desc")}
        ></div>
      </div>
    ),
    cellRenderer: ({ cellData: desc }) => <div class="row">{desc}</div>,
  },
]);

const data = ref(Array.from({ length: 200 }).map(dataGenerator));

// 拖动改变列宽相关逻辑
const columnRefresh = (x, fileKey) => {
  let columnItem = columns.value.find((item) => item.dataKey === fileKey) || {};
  columnItem.width = columnItem.width + x;
};
let x1, x2;
var dragStart = (e) => {
  x1 = e.x;
};
var dragEnd = (e, fileKey) => {
  x2 = e.x;
  let x = x2 - x1;
  columnRefresh(x, fileKey);
};
</script>
<style lang="less">
.header-box {
  position: relative;
  flex: 1;
  .drag-line {
    position: absolute;
    top: -9px;
    right: -8px;
    bottom: -9px;
    cursor: ew-resize;
    width: 1px;
    padding-left: 6px;
    border-right: 1px solid #d8d8d8;
    background: transparent;
  }
}
.row {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
</style>