鼠标滑动选中表格部分数据列(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);
        },
    }
}
相关推荐
Devil枫2 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
GIS程序媛—椰子3 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山3 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享4 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果4 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄5 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰5 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
清灵xmf6 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
薛一半7 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js
Mac新人7 小时前
又发现了Mac妙控鼠标的新使用方法
计算机外设