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

文章目录

代码

指令代码

js 复制代码
// 获得鼠标移动的范围
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';
        };
    },
};

使用代码

html 复制代码
<!-- 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>
js 复制代码
// 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);
        },
    }
}
相关推荐
非凡ghost3 分钟前
Subtitle Edit(字幕编辑软件) 中文绿色版
前端·javascript·后端
用户84298142418106 分钟前
10个JavaScript编程实用技巧
javascript
扎瓦斯柯瑞迫7 分钟前
cursor: 10分钟魔改环境、优雅获取Token
前端·javascript·后端
wuxingxi9 分钟前
现代化企业级H5模板:Vite + Vue 3 + TypeScript 开箱即用
vue.js
Violet_YSWY14 分钟前
将axios、async、Promise联系在一起讲一下&讲一下.then 与其关系
开发语言·前端·javascript
San3018 分钟前
扩展卡片效果:用 Flexbox 和 CSS 过渡打造惊艳交互体验
前端·javascript·css
写代码的皮筏艇20 分钟前
JS数据类型转换
前端·javascript
Qinana22 分钟前
🌟 从 CSS 到 Stylus:打造更优雅、高效的样式开发体验
前端·javascript·css
Joker`s smile25 分钟前
vue + elementUI 实现特殊字符(上标、下标、特殊符号等)输入框
vue.js·elementui·特殊字符·unicode字符·上标·下标
程序员Sunday25 分钟前
还在用 setTimeout?试试 requestIdleCallback 吧!
前端·javascript