鼠标滑动选中表格部分数据列(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);
        },
    }
}
相关推荐
就改了6 分钟前
Ajax——在OA系统提升性能的局部刷新
前端·javascript·ajax
凌冰_8 分钟前
Ajax 入门
前端·javascript·ajax
奋飛33 分钟前
TypeScript系列:第六篇 - 编写高质量的TS类型
javascript·typescript·ts·declare·.d.ts
sunbyte41 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)
前端·javascript·css·vue.js·前端框架·tailwindcss
小飞悟1 小时前
🎯 什么是模块化?CommonJS 和 ES6 Modules 到底有什么区别?小白也能看懂
前端·javascript·设计
浏览器API调用工程师_Taylor1 小时前
AOP魔法:一招实现登录弹窗的全局拦截与动态处理
前端·javascript·vue.js
FogLetter1 小时前
初识图片懒加载:让网页像"懒人"一样聪明加载
前端·javascript
呆呆的心1 小时前
JavaScript 深入理解闭包与柯里化:从原理到实践 🚀
javascript·面试
快起来别睡了1 小时前
看完这篇文章,你就知道什么是proxy
javascript
请你吃div1 小时前
JavaScript 实用函数大全(超实用)
前端·javascript·面试