antDesignVue1.7.8的table组件添加列滑动,亲测该demo是OK的
主要包括两个文件一个demo.vue和header.js
demo.vue文件代码
<a-table ref="baseTable" bordered :components="componentsa" :columns="columns" :dataSource="hxrData" :rowKey="(record, index) => index" :pagination="false"></a-table>
<script>
import { ResizeHeader, customHeaderCell, ResizeColumnProvide } from './header'
export default {
computed: {
componentsa() {
// 重新header部分逻辑
return {
header: {
cell: ResizeHeader,
},
}
},
},
mixins: [ResizeColumnProvide],
data(){
return {
columns: [],
hxrColumns: [
{
title: 'Age',
dataIndex: 'age',
key: 'age',
resizable: true, // 可拖拽标识
width: 80 // 注意如果要设可拖拽,要先设宽度
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
scopedSlots: { customRender: 'tags' },
},
{
title: 'Action',
key: 'action',
scopedSlots: { customRender: 'action' },
},
],
hxrData: [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
],
}
},
mounted() {
//给column绑定 不绑定的话ResizeHeader方法中的参数props无法获取到column信息
//这里的hxrColumns就是表头的集合
this.columns = this.hxrColumns.map((item) => Object.assign({}, item, { customHeaderCell }))
}
}
</script>
<style>
.nio-header-th {
position: relative;
isolation: isolate;
}
.nio-drag-handler {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: 2px;
z-index: 1;
border: 1px dashed #eee;
&:hover,
&:focus {
cursor: col-resize;
border: 1px dashed #0bd9d9;
}
}
</style>
header.js文件代码
function noop() {
}
//重构table组件的核心渲染函数
export const ResizeHeader = (h, props, children) => {
const { key, column, ...restProps } = props;
let content = [].concat(children);
console.log('column', column)
if (column.resizable) {
const handlerVNode = h(DragHandler, {
props: {
width: column.width,
minWidth: Math.min(column.width, 100),
column: column
}
}, []);
content = content.concat(
handlerVNode
);
}
return h("th", {
key,
props: { column },
...Object.assign({}, restProps, { class: (restProps.class || "") + " nio-header-th" })
}, content);
};
const events = {
start: "mousedown",
move: "mousemove",
stop: "mouseup",
};
//对table组件进行重构的核心方法组件
const DragHandler = {
name: "nio-drag-handler",
//获取混入的方法(重新设置表头宽度)
inject: {
onResizeColumn: {
default: noop
}
},
props: {
column: { type: Object, required: true },
minWidth: { type: Number, required: true }
},
data() {
return {
dragging: false,
thWidth: 0,// 列头的宽度,用于计算
startX: 0,
moveEvent: {
remove: noop
},
stopEvent: {
remove: noop
}
};
},
//销毁监听
beforeDestroy() {
this.removeEvents();
},
methods: {
//鼠标开始拖拽
handleMouseDown(e) {
e.stopPropagation();
e.preventDefault();
this.handleStart(e);
},
handleStart(e) {
this.dragging = true;
this.removeEvents();
this.thWidth = this.$el.parentNode.getBoundingClientRect().width;
if (e instanceof MouseEvent && e.which !== 1) {
return;
}
if (e.stopPropagation) e.stopPropagation();
this.startX = e.pageX;
this.moveEvent = addEventListenerWrap(document.documentElement, events.move, this.handleMove);
this.stopEvent = addEventListenerWrap(document.documentElement, events.stop, this.handleStop);
},
handleMove(e) {
this.updateWidth(e);
},
handleStop(e) {
this.dragging = false;
this.updateWidth(e);
this.removeEvents();
},
updateWidth(e) {
let pageX = e.pageX;
const tmpDeltaX = this.startX - pageX;
let w = Math.max(this.thWidth - tmpDeltaX, this.minWidth);
w = Math.min(w, Infinity);
this.onResizeColumn(w, this.column);
},
removeEvents() {
this.moveEvent.remove();
this.stopEvent.remove();
}
},
//渲染div 绑定拖拽
render(h) {
const line = h("div", { class: "nio-drag-handler-line" }, []);
return h("div", { class: "nio-drag-handler", on: { mousedown: this.handleMouseDown } }, [line]);
}
};
//监听鼠标移动的方法
function addEventListenerWrap(target, eventType, cb) {
if (target && target.addEventListener) {
target.addEventListener(eventType, cb);
}
return {
remove: () => {
if (target && target.removeEventListener) {
target.removeEventListener(eventType, cb);
}
},
};
}
//在table组件中混入的一个方法 provide => onResizeColumn
//目的是在table重写中(DragHandler方法)
//可以用到构造的onResizeColumn方法(重新设置表头的宽度)
export const ResizeColumnProvide = {
name: "ResizeColumnProvideMixin",
provide() {
return {
onResizeColumn: this.onResizeColumn
};
},
data() {
const onResizeColumn = throttle2(this._resizeColumn, 30);
return {
columnsKey: "columns", //这个属性是table组件表头的集合名称 :columns="columns"
moving:false, //这个属性是为了在拖拽时 阻止表头触发排序的功能
onResizeColumn
};
},
methods: {
_resizeColumn(w, column) {
const columns = this[this.columnsKey];
this.moving = true
let time = setTimeout(() => {
this.moving = false
clearTimeout(time)
}, 2000);
//在拖拽时找到对应表头 重新设置表头的宽度
//这就是为什么表头column要绑定customHeaderCell的原因
const matchedIndex = columns.findIndex(item => item.key === column.key);
columns[matchedIndex].width = w;
}
}
};
//拖拽的节流方法
const throttle2 = (fn, delay) => {
let valid = true;
return (...args) => {
if (!valid) {
return;
}
valid = false;
setTimeout(() => {
fn(...args);
valid = true;
}, delay);
};
};
//table组件内置的一个方法
export function customHeaderCell(column) {
return Object.assign({
column: column
});
}