鼠标滑动选中表格部分数据列(vue指令)

代码

指令代码

// 获得鼠标移动的范围
function getMoveRange(startClientX, endClientX, startClientY, endClientY) {
    const _startClientX = Math.min(startClientX, endClientX);
    const _endClientX = Math.max(startClientX, endClientX);
    const _startClientY = Math.min(startClientY, endClientY);
    const _endClientY = Math.max(startClientY, endClientY);
    // 判断鼠标移动的距离是否大于 10
    const moveX = _endClientX - _startClientX;
    const moveY = _endClientY - _startClientY;
    return {
        moveX,
        moveY,
    };
}

// 获得鼠标划过的行索引
function getRowRangeIndex(startRowIndex, endRowIndex) {
    const start = Math.min(startRowIndex, endRowIndex);
    const end = Math.max(startRowIndex, endRowIndex);
    return {
        start,
        end,
    };
}

const rangeselect = {
    async bind(el, binding, vnode) {
        const rangeDiv = document.createElement('div');
        rangeDiv.id = 'rangeSelectDiv';
        rangeDiv.style.display = 'none';
        rangeDiv.style.position = 'absolute';
        rangeDiv.style.pointerEvents = 'none';
        rangeDiv.style.zIndex = 9999;
        rangeDiv.style.backgroundColor = '#0088ff40';
        rangeDiv.style.top = 0;
        rangeDiv.style.left = 0;
        rangeDiv.style.border = '1px solid #0088ff';
        document.body.append(rangeDiv);
        let mousedown = false;
        let startRowIndex = -1;
        let endRowIndex = -1;
        let startClientX = 0; // 用于计算移动的距离
        let startClientY = 0; // 用于计算移动的距离
        let endClientX = 0; // 用于计算移动的距离
        let endClientY = 0; // 用于计算移动的距离
        const { componentInstance: $table } = await vnode;
        el.onmousedown = (event) => {
            const cell = event.target.closest('td');
            if (cell) {
                const elCheckboxElement = cell.querySelector('.el-checkbox');
                if (elCheckboxElement) {
                    event.preventDefault();
                    mousedown = true;
                    const rowIndex = cell.parentNode.rowIndex;
                    if (binding.value.handleMouseDown) {
                        binding.value.handleMouseDown(rowIndex);
                    }
                    startRowIndex = rowIndex;
                    endRowIndex = rowIndex;
                    startClientX = event.clientX;
                    startClientY = event.clientY;
                    endClientX = event.clientX;
                    endClientY = event.clientY;
                    rangeDiv.style.top = `${startClientY}px`;
                    rangeDiv.style.left = `${startClientX}px`;
                    rangeDiv.style.display = 'block';
                }
            }
        };
        el.onmousemove = (event) => {
            if (mousedown) {
                el.style.userSelect = 'none';
                event.preventDefault();
                endClientX = event.clientX;
                endClientY = event.clientY;
                const xDiff = endClientX - startClientX;
                const yDiff = endClientY - startClientY;
                rangeDiv.style.height = `${Math.abs(yDiff)}px`;
                rangeDiv.style.width = `${Math.abs(xDiff)}px`;
                if (xDiff >= 0 && yDiff >= 0) {
                    rangeDiv.style.transform = '';
                } else if (xDiff < 0 && yDiff < 0) {
                    rangeDiv.style.top = `${endClientY}px`;
                    rangeDiv.style.left = `${endClientX}px`;
                } else if (xDiff > 0 && yDiff < 0) {
                    rangeDiv.style.top = `${endClientY}px`;
                } else if (xDiff < 0 && yDiff > 0) {
                    rangeDiv.style.left = `${endClientX}px`;
                }
                const moveRange = getMoveRange(startClientX, endClientX, startClientY, endClientY);
                // 判断鼠标移动的距离是否大于 10
                if (moveRange.moveY > 10 && moveRange.moveX > 5 && startRowIndex > -1 && endRowIndex > -1) {
                    const cell = event.target.closest('td');
                    if (cell) {
                        const rowIndex = cell.parentNode.rowIndex;
                        endRowIndex = rowIndex;
                        const rowRangeIndex = getRowRangeIndex(startRowIndex, endRowIndex);
                        if (!event.ctrlKey) {
                            $table.clearSelection();
                        }
                        for (let i = rowRangeIndex.start; i <= rowRangeIndex.end; i++) {
                            if (binding.value.handleMousemove) {
                                binding.value.handleMousemove(i, true)
                            }
                        }
                    }
                }
            }
        };
        el.onmouseup = () => {
            mousedown = false;
            rangeDiv.style.height = '0px';
            rangeDiv.style.width = '0px';
            rangeDiv.style.top = '0px';
            rangeDiv.style.left = '0px';
            rangeDiv.style.display = 'none';
            startRowIndex = -1;
            endRowIndex = -1;
            el.style.userSelect = 'text';
        };
    },
};



使用代码

<!-- vue-template -->
<el-table ref="tableRef" v-rangeselect="{handleMousemove}" :data="tableData" border stripe>
	<el-table-column type="selection" width="55"></el-table-column>
	<el-table-column label="序号" width="60"></el-table-column>
</el-table>
// vue-script
{
	data() {
        return {
            tableData: [],
        }
    },
    directives: {
        rangeselect
    },
    methods: {
        handleMousemove(rowIndex, checked) {
            const table = this.$refs.tableRef;
            const tempTableData = this.tableData[rowIndex];
            table.toggleRowSelection(tempTableData, checked);
        },
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

范德萨_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值