<template>
<a-card>
<a-table
:columns="columns"
:components="drag(columns)"
:data-source="data"
:size="attrBute.cellsize"
bordered
:rowKey="(record, index) => index"
:pagination="attrBute.pagination"
class="table"
>
</a-table>
</a-card>
</template>
<script>
import Vue from "vue";
import VueDraggableResizable from "vue-draggable-resizable";
Vue.component("vue-draggable-resizable", VueDraggableResizable);
export default {
data() {
return {
columns: [
{
title: "基本信息",
children: [
{
title: "大学",
dataIndex: "name",
key: "name",
width: 100,
},
{
title: "年龄",
dataIndex: "age",
key: "age",
width: 100,
},
],
},
{
title: "学校信息",
children: [
{
title: "大学",
dataIndex: "daxue",
key: "daxue",
width: 100,
},
{
title: "学历",
dataIndex: "xueli",
key: "xueli",
width: 100,
},
],
},
{
title: "户籍",
dataIndex: "huji",
width: 300,
},
],
data: [
{
name: "张三",
age: "18",
daxue: "长江大学",
xueli: "研究生",
huji: "湖北襄阳",
},
],
maxLevel: 1,
cellsize: "small",
attrBute: {
bordered: false,
pagination: false,
isIndex: false, // index 序列
isCheck: false, // 是否有复选框
isTree: false,
cellsize: "small",
},
};
},
methods: {
drag(columns) {
return {
header: {
cell: this.initDrag(columns),
},
};
},
/**
* @param { 表格columns } tbCols
*/
initDrag(tbCols) {
let draggingMap = {};
this.getDraggingMap(tbCols, draggingMap, 1);
let draggingState = Vue.observable(draggingMap);
return (h, props, children) => {
let thDomIndex = 0;
const { key, ...restProps } = props;
let col = {};
// 处理多级表头
col = this.getRenderCoL(key, tbCols);
if (!col || !col.width) {
//这儿要求表格数据中要有宽width属性,若是没有是不会执行下面的拖拽的
return <th {...restProps}>{children}</th>;
}
const onDrag = (x) => {
col.width = Math.max(x, 1);
draggingState[key] = col.width;
thDomIndex = 0;
loopDom(tbCols, col);
// 自带复选框 列
if (!this.attrBute.isCheck) {
thDomIndex--;
}
let colgroup = document.querySelectorAll("colgroup");
colgroup.forEach((Element) => {
let childCol = Element.children;
if (childCol[thDomIndex])
childCol[thDomIndex].style.width = col.width + "px";
});
// 固定列情况,resetFixedColumns中的参数 width 要经过计算得到整个变化后的table-fixed-left的宽度
if (col.fixed)
this.resetFixedColumns(col.width + this.attrBute.isCheck ? 60 : 0);
};
const loopDom = (cols, col) => {
let tag = true;
this._.forEach(cols, (co) => {
if (co.dataIndex == col.dataIndex) {
thDomIndex++;
tag = false;
return tag;
}
if (co.children) {
tag = loopDom(co.children, col);
return tag;
} else {
thDomIndex++;
}
});
return tag;
};
const onDragstop = () => {};
let helper;
if (col.helper) {
helper = <span>{this.$slots[col.dataIndex + "_helper"]}</span>;
}
return (
<th
{...restProps}
width={draggingState[key]}
class="resize-table-th"
dataIndex={col.key}
>
{children}
{helper}
<vue-draggable-resizable
key={col.dataIndex || col.key}
class="table-draggable-handle"
w={20}
h={this.getResizableHandler(col)}
x={draggingState[key]}
z={100}
axis="x"
draggable={true}
resizable={false}
onDragging={onDrag}
onDragstop={onDragstop}
></vue-draggable-resizable>
</th>
);
};
},
getheadT(d) {
return d.newTitle;
},
getheadTis(d) {
return d.tips;
},
getResizableHandler(col) {
// let baseH = thDom.getBoundingClientRect().height;
// 单元格size
let size = this.cellsize ? this.cellsize : this.attrBute.cellsize;
let baseH = size == "middle" ? 47 : size == "small" ? 39 : 55;
if (col.isEndNode) return baseH * col.nodeLevel;
else if (col.leafNode && col.nodeLevel < this.maxLevel) {
return baseH * this.maxLevel;
} else return baseH;
},
resetFixedColumns(width) {
const fixedHead = document.querySelector(
".ant-table-fixed-left .ant-table-header"
);
const fixedBody = document.querySelector(
".ant-table-fixed-left .ant-table-body-outer .ant-table-fixed"
);
if (fixedHead) {
fixedHead.style.width = width + "px";
fixedBody.style.width = width + "px";
}
},
getDraggingMap(tbCols, draggingMap, nodeLevel) {
tbCols.forEach((col, index) => {
col.nodeLevel = nodeLevel;
col.isEndNode = index == tbCols.length - 1;
this.maxLevel = Math.max(this.maxLevel, nodeLevel);
if (col.children) {
col.leafNode = false;
this.getDraggingMap(col.children, draggingMap, nodeLevel + 1);
} else {
col.leafNode = true;
const key = col.dataIndex || col.key; //这儿要求表格数据中要有这两个属性
draggingMap[key] = col.width || 0;
}
});
},
getRenderCoL(key, tbCols) {
let result = "";
this._.forEach(tbCols, (item) => {
if (item.children) {
result = this.getRenderCoL(key, item.children);
return !result;
} else {
const k = item.dataIndex || item.key;
if (k === key) {
result = item;
return false;
}
}
});
return result;
},
},
};
</script>
<style lang="less">
/* vue-draggable-resizable@2.1.0 begin */
.resize-table-th {
position: relative;
overflow: hidden;
}
.resize-table-th .table-draggable-handle {
height: 100% !important;
bottom: 0;
left: auto !important;
right: -5px;
cursor: col-resize;
touch-action: none;
}
/* 插件 end */
</style>
安装lodash
npm install lodash --save
在main.js中注册
import _ from 'lodash'
Vue.prototype._ = _