?
實(shí)現(xiàn)思路: 項(xiàng)目有兩個(gè)需求,既能在el-table實(shí)現(xiàn)點(diǎn)選又能實(shí)現(xiàn)鼠標(biāo)框選
一. 點(diǎn)選實(shí)現(xiàn)思路: 使用el-table的cellClick方法,
????????1.直接給點(diǎn)擊的cell添加類名,cell.classList.add("blue-cell");然后把獲取的數(shù)據(jù)存入數(shù)組,
???????????設(shè)置樣式:
::v-deep .el-table td.blue-cell { border: 1px solid blue !important; }
? ? ?方法2.如果不添加類名,可以在cellStyle方法里通過存儲(chǔ)的數(shù)組添加邊框,如果是普通滾動(dòng)可以使用行索引,如果是虛擬滾動(dòng),這里需要使用id更為準(zhǔn)確文章來源:http://www.zghlxwxcb.cn/news/detail-592729.html
cellStyle({ row, column, rowIndex, columnIndex }) { // 對(duì)xqArr選擇選區(qū)的單元格加藍(lán)邊框 let matchObj = this.xqArr.find( item => item.column === column.index && // item.row === row.index && item.rowId === row.id && item.sampleTime === row.sampleTime ); if (matchObj) { return { border: "1px solid #5E99FD" }; } }
二.鼠標(biāo)框選實(shí)現(xiàn)思路: 利用鼠標(biāo)按下和抬起事件,計(jì)算框的范圍,框住的cell可以通過類名添加邊框或者依然通過數(shù)組形式. 需要注意的是因?yàn)閑l-table在頁面的右下方,并且數(shù)據(jù)量大,可以滾動(dòng),所以需要在計(jì)算距離的時(shí)候需要減去容器偏移的距離和滾動(dòng)的高度.文章來源地址http://www.zghlxwxcb.cn/news/detail-592729.html
<el-table
border
:lazy="true"
v-loading="loading"
@cell-click="cellClick"
:cell-class-name="tableCellClassName"
@row-contextmenu="rightClick"
@row-click="clickTableRow"
@mousedown.native="down($event)"
@mousemove.native="move($event)"
@mouseup.native="up($event)"
:data="historyDataTables"
:highlight-current-row="true"
:stripe="true"
:header-cell-style="{
background: '#cff7ff',
fontWeight: 'bold',
color: '#080809'
}"
:row-height="30"
:total="totalCount"
:cell-style="cellStyle"
:max-height="maxHeight1"
@selection-change="handleSelectionChange"
ref="multipleTable"
:row-key="row => row.id"
id="table"
>
<script>
export default {
data() {
return {
// 列表集合
historyDataTables: [],
select: false,
isMouseDown: true, // 是否需要(允許)處理鼠標(biāo)的移動(dòng)事件
// 定義移動(dòng)元素div
rect: null,
// 記錄鼠標(biāo)按下時(shí)的坐標(biāo)
downX: 0,
downY: 0,
// 記錄鼠標(biāo)抬起時(shí)候的坐標(biāo)
mouseX2: this.downX,
mouseY2: this.downY,
// 表格dom元素
TableDom: null,
tableHeaderHeight: 0,
selectedData: [], // 鼠標(biāo)框選選中的數(shù)據(jù)
selectedCellTop: 0, // 選中單元格距離el-table頂部的距離
selectedCellLeft: 0, // 選中單元格距離el-table左側(cè)的距離
tableRectTop: 0, // el-table距離window頂部的距離
tableRectLeft: 0, // el-table距離window左側(cè)的距離
tableScrollTop: 0, // el-table滾動(dòng)的距離
}
},
mounted() {
this.TableDom = this.$refs.multipleTable.$el; // 獲取table元素
// 獲取table的位置,監(jiān)聽窗口變化,table的距離變化
this.getTableMarginLeft();
window.addEventListener("resize", this.getTableMarginLeft);
this.clientWidth =
document.documentElement.clientWidth || document.body.clientWidth;
this.clientHeight =
document.documentElement.clientHeight || document.body.cientHeight;
this.otherHeight =
Math.ceil($(".is-always-shadow").outerHeight()) +
Math.ceil($(".is-top").outerHeight());
this.maxHeight1 = this.clientHeight - this.otherHeight - 150 + "px";
var that = this;
window.onresize = () => {
return (() => {
window.clientHeight =
document.documentElement.clientHeight || document.body.clientHeight;
that.clientHeight = window.clientHeight;
})();
};
},
beforeDestroy() {
window.removeEventListener("resize", this.getTableMarginLeft);
},
methods: {
// 獲取table距離頁面左側(cè)和上方的距離
getTableMarginLeft() {
const tableRect = this.TableDom.getBoundingClientRect(); // 獲取el-table元素的位置信息
this.tableRectTop = Math.ceil(tableRect.top);
this.tableRectLeft = Math.ceil(tableRect.left);
},
down(event) {
// 當(dāng)允許鼠標(biāo)按下時(shí),才允許處理鼠標(biāo)的移動(dòng)事件,這里結(jié)合項(xiàng)目其他問題所以設(shè)置了判斷條件
if (this.isMouseDown) {
this.select = true;
this.rect = document.createElement("div");
// 框選div 樣式
this.rect.style.cssText =
"position:absolute;width:0px;height:0px;font-size:0px;margin:0px;padding:0px;border:1px solid #0099FF;background-color:#C3D5ED;z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";
this.rect.id = "selectDiv";
this.getTableMarginLeft();
const container = document.querySelector(".el-table__body-wrapper"); // 獲取table容器元素
this.TableDom.appendChild(this.rect); // 添加到table元素下
// 取得鼠標(biāo)按下時(shí)的坐標(biāo)位置
this.downX =
event.x || event.clientX + container.scrollLeft - this.tableRectLeft; // 鼠標(biāo)按下時(shí)的x軸坐標(biāo) event.x 兼容火狐瀏覽器, event.clientX 兼容谷歌瀏覽器
this.downY =
event.y || event.clientY + container.scrollTop - this.tableRectTop; // 鼠標(biāo)按下時(shí)的y軸坐標(biāo)
this.rect.style.left = this.downX + "px"; // 設(shè)置你要畫的矩形框的起點(diǎn)位置
this.rect.style.top = this.downY + "px"; // 設(shè)置你要畫的矩形框的起點(diǎn)位置
//設(shè)置你要畫的矩形框的起點(diǎn)位置
this.rect.style.left = this.downX; // 因?yàn)樵诨鸷鼮g覽器下,上面的代碼不起作用,所以在這里再寫一遍,為什么火狐瀏覽器不起作用,因?yàn)榛鸷鼮g覽器下,我們的div是絕對(duì)定位的,所以我們要加上px,為什么這里沒加px,因?yàn)槲覀兿旅嬉由蟨x,所以這里不用加
this.rect.style.top = this.downY;
} else {
return;
}
},
move(event) {
/*
這個(gè)部分,根據(jù)你鼠標(biāo)按下的位置,和你拉框時(shí)鼠標(biāo)松開的位置關(guān)系,可以把區(qū)域分為四個(gè)部分,根據(jù)四個(gè)部分的不同,
我們可以分別來畫框,否則的話,就只能向一個(gè)方向畫框,也就是點(diǎn)的右下方畫框.
*/
if (this.select && this.isMouseDown) {
// 取得鼠標(biāo)移動(dòng)時(shí)的坐標(biāo)位置
this.mouseX2 = event.clientX; // 鼠標(biāo)移動(dòng)時(shí)的x軸坐標(biāo)
this.mouseY2 = event.clientY; // 鼠標(biāo)移動(dòng)時(shí)的y軸坐標(biāo)
// 框選元素的顯示與隱藏
if (this.rect.style.display == "none") {
this.rect.style.display = "";
}
// 框選元素的位置處理
this.rect.style.left =
Math.min(this.mouseX2, this.downX) - this.tableRectLeft + "px";
this.rect.style.top =
Math.min(this.mouseY2, this.downY) - this.tableRectTop + "px"; // 取得鼠標(biāo)拉框時(shí)的起點(diǎn)坐標(biāo)
this.rect.style.width = Math.abs(this.mouseX2 - this.downX) + "px"; // 取得鼠標(biāo)拉框時(shí)的寬度
this.rect.style.height = Math.abs(this.mouseY2 - this.downY) + "px"; // 取得鼠標(biāo)拉框時(shí)的高度
// A part
if (this.mouseX2 < this.downX && this.mouseY2 < this.downY) {
this.rect.style.left = this.mouseX2 + this.tableRectLeft;
this.rect.style.top = this.mouseY2 + this.tableRectTop;
}
// B part
if (this.mouseX2 > this.downX && this.mouseY2 < this.downY) {
this.rect.style.left = this.downX + this.tableRectLeft;
this.rect.style.top = this.mouseY2 + this.tableRectTop;
}
// C part
if (this.mouseX2 < this.downX && this.mouseY2 > this.downY) {
this.rect.style.left = this.mouseX2 + this.tableRectLeft;
this.rect.style.top = this.downY + this.tableRectTop;
}
// D part
if (this.mouseX2 > this.downX && this.mouseY2 > this.downY) {
this.rect.style.left = this.downX + this.tableRectLeft;
this.rect.style.top = this.downY + this.tableRectTop;
}
} else {
return;
}
this.stopEvent(event);
},
// 阻止默認(rèn)事件
stopEvent(event) {
if (event.stopPropagation) {
// 標(biāo)準(zhǔn)瀏覽器
event.stopPropagation(); // 阻止事件冒泡
event.preventDefault(); // 阻止默認(rèn)事件
} else {
// IE瀏覽器
event.cancelBubble = true;
event.returnValue = false;
}
},
// 鼠標(biāo)抬起事件
up() {
if (this.select && this.isMouseDown) {
const container = document.querySelector(".el-table__body-wrapper"); // 獲取table容器元素
const scrollTop = container.scrollTop; // 獲取el-table的scrollTop和scrollLeft
const scrollLeft = container.scrollLeft;
const headerWrapper = this.TableDom.querySelector(
".el-table__header-wrapper"
);
const tableHeaderHeight = Math.ceil(
headerWrapper.getBoundingClientRect().height
);
const columns = this.$refs.multipleTable.columns; // 表格的標(biāo)題
const rectLeft = this.rect.offsetLeft + scrollLeft - this.tableRectLeft;
const rectTop =
this.rect.offsetTop +
scrollTop -
this.tableRectTop -
tableHeaderHeight;
const tableBody = document.querySelector(".el-table__body");
tableBody.children[1].childNodes.forEach(element => {
for (let index = 0; index < element.childNodes.length; index++) {
// 獲取當(dāng)前單元格
const cell = element.childNodes[index];
if (
// 判斷選中的單元格是否在鼠標(biāo)拉框的范圍內(nèi)
rectLeft <
cell.offsetLeft - this.tableRectLeft + cell.offsetWidth &&
rectLeft + this.rect.offsetWidth >
cell.offsetLeft - this.tableRectLeft &&
rectTop <
cell.offsetTop - this.tableRectTop + cell.offsetHeight &&
rectTop + this.rect.offsetHeight >
cell.offsetTop - this.tableRectTop &&
index >= 3 // 選中的單元格所在列的索引大于等于3
) {
if (cell.className.indexOf("add") == -1) {
// cell.style.border = "1px solid red";
const cellText = cell.innerText;
const rowData = this.historyDataTables[element.rowIndex]; // 獲取當(dāng)前單元格所在的行數(shù)據(jù)
// 獲取表格的列名的屬性名property
let columnProperty = undefined;
// 遍歷第一行數(shù)據(jù)
// console.log(index, '--index--'); // 框選數(shù)據(jù)所在列的索引
for (const item of columns) {
if (item.index === index) {
columnProperty = item.property;
break;
}
}
// const rowIndex = element.rowIndex; // 將當(dāng)前單元格所在的行數(shù)據(jù)加入到該列數(shù)據(jù)中
const columnIndex = index;
const time = rowData.sampleTime;
// 選擇要添加到選中行數(shù)組中的屬性
const selected = {
rowId: rowData.id,
// row: rowIndex,
column: columnIndex,
sampleTime: time,
factor: columnProperty,
tag: rowData[columnProperty + "_tag"] || "",
tagStatus: rowData[columnProperty + "_tag_status"] || "",
mark: rowData[columnProperty + "_mark"] || ""
};
// 將選中數(shù)據(jù)加入到狀態(tài)中已有的數(shù)據(jù)中,如果已有相同的數(shù)據(jù),則不加入
if (
!this.selectedData.some(data => this.isEqual(data, selected))
) {
this.selectedData.push(selected);
}
// 將選中數(shù)據(jù)加入到 xqArr 中
this.selectedData.forEach(item => {
// 如果 xqArr 中已有相同數(shù)據(jù),則不加入
if (!this.xqArr.some(data => this.isEqual(data, item))) {
this.xqArr.push(item);
}
});
this.selectedData = [];
}
}
}
});
//鼠標(biāo)抬起,就不允許在處理鼠標(biāo)移動(dòng)事件
this.select = false;
//隱藏圖層
if (this.rect) {
this.TableDom.removeChild(this.rect);
}
} else {
return;
}
},
// 定義方法 isEqual 來比較兩個(gè)選中數(shù)據(jù)對(duì)象是否相同
isEqual(data1, data2) {
return (
data1.rowId === data2.rowId &&
data1.column === data2.column &&
data1.sampleTime === data2.sampleTime &&
data1.factor === data2.factor
);
}
}
}
到了這里,關(guān)于vue中實(shí)現(xiàn)el-table點(diǎn)選和鼠標(biāo)框選功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!