文章目录
代码
指令代码
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);
},
}
}