VUE a-table 动态拖动修改列宽+固定列

实现效果

请添加图片描述

实现思路

  1. 自定义表头,在标题后面加两个标签,分别用来显示拖拽图标(cursor: col-resize),和蓝色标记线(有的时候鼠标移动过程中不一定会在表内,这个时候不显示图标,只显示蓝色标记线)
  2. 给所有列增加一个初始宽度,表格 scroll 的 x 设置为100%
  3. 点击拖拽图标后:显示对应的蓝色标记线,监听鼠标的移动和释放
  4. 鼠标移动的时候同步更新列宽
  5. 鼠标释放的时候移除监听

实现代码

html

<a-table
    :scroll="{ x: '100%' }"
    :columns="columns"
    :data-source="dataSource"
>
    <template #headerCell="{ column }">
        <div class="resizable-header">
            {{ column.title }}
            <span class="resizer" @mousedown="(e) => onMouseDown(e, column)"></span>
            <span v-if="isResizing && resizingColumnKey === column.key" class="resizer-line"></span>
        </div>
    </template>
</a-table>

ts

const columns = ref<Array<any>>([]);
const isResizing = ref(false);
const resizingColumnKey = ref<string>('');

// 设置列字段,列宽、固定列
watch(
   () => headerColumns.value,
   () => {
	   columns.value = headerColumns.value.map((obj: HeaderColumns) => {
		    if (item.name === 'code') {
		        obj = { ...obj, width: 150, fixed: true };
		    } else if (item.name === 'seq') {
		        obj = { ...obj, width: 50, fixed: true };
		    } else if (item.name === 'operation') {
		        delete obj.ellipsis;
		        obj = { ...obj, width: 200, fixed: 'right' };
		    } else {
		        obj = { ...obj, width: (obj.title || '').length * 15 + 18 };
		    }
		    return obj;
		});
   },
   {
        immediate: true,
        deep: true,
    },
);

// 点击拖拽设置列宽
const onMouseDown = (event: MouseEvent, column: any) => {
    const startX = event.clientX; // 获取鼠标初始位置
    const startWidth = column.width || 0; // 获取初始宽度
    isResizing.value = true;
    resizingColumnKey.value = column.key;

    const mouseMoveHandler = (e: MouseEvent) => {
        if (!isResizing.value || !resizingColumnKey.value) return;

        const newWidth = Math.max(50, parseFloat(`${startWidth}`) + (e.clientX - startX)); // 计算新的宽度
        column.width = newWidth; // 更新列宽
    };

    const mouseUpHandler = () => {
        isResizing.value = false;
        resizingColumnKey.value = '';
        document.removeEventListener('mousemove', mouseMoveHandler);
        document.removeEventListener('mouseup', mouseUpHandler);
    };

    document.addEventListener('mousemove', mouseMoveHandler);
    document.addEventListener('mouseup', mouseUpHandler);
};

css

:deep(.ant-table-cell-ellipsis.ant-table-cell-fix-left-last .ant-table-cell-content) {
    overflow: visible;
}

.resizable-header {
    position: relative;
    display: flex;
    align-items: center;

    .resizer {
        position: absolute;
        top: 0;
        right: -12px;
        z-index: 1;
        width: 8px;
        height: 100%;
        cursor: col-resize;
    }

    .resizer-line {
        position: absolute;
        top: -8px;
        right: -8px;
        bottom: -8px;
        width: 1px;
        background-color: #3388FF;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值