ElementUI table自帶的有一個(gè)highlight-current-row
的屬性况木,但是只能單選垒拢。所以要實(shí)現(xiàn)點(diǎn)擊行選中以及多選得自己實(shí)現(xiàn).
目標(biāo):單擊選中/取消旬迹, 按ctrl
鍵點(diǎn)擊實(shí)現(xiàn)多選 ,按shift/alt
鍵實(shí)現(xiàn)連續(xù)多選求类。
實(shí)現(xiàn)效果
GIF.gif
1. 監(jiān)聽row-click
事件奔垦,實(shí)現(xiàn)選中
<el-table ref="multipleTable"
:data="tableData"
style="width: 100%"
@selection-change="handleSelectionChange"
@row-click="rowClick"
:row-style="rowStyle"
:row-class-name="rowClassName">
.....
.....
</el-table>
rowClick(row, column, event) {
let refsElTable = this.$refs.multipleTable; // 獲取表格對象
refsElTable.toggleRowSelection(row); // 調(diào)用選中行方法
}
2. 實(shí)現(xiàn)選中取消,以及單個(gè)選中
上面已經(jīng)實(shí)現(xiàn)點(diǎn)擊選中仑嗅,但是會點(diǎn)擊一行選中一行宴倍,所以要使用clearSelection
先清空之前選擇的行,然后進(jìn)行選擇仓技,取消選擇首先要確定當(dāng)前點(diǎn)擊的行是否被已被選中鸵贬,所以先監(jiān)聽selection-change
事件保存已選中行(或者使用$refs
獲取內(nèi)部保存的已選擇行),以及使用row-style
給每一行添加唯一標(biāo)識脖捻。
rowClick(row, column, event) {
let refsElTable = this.$refs.multipleTable; // 獲取表格對象
let findRow = this.selectionRow.find(c => c.rowIndex == row.rowIndex);
if (findRow ) {
refsElTable.toggleRowSelection(row, false);
return;
}
refsElTable.clearSelection();
refsElTable.toggleRowSelection(row); // 調(diào)用選中行方法
}阔逼,
rowStyle({row,rowIndex}) {
Object.defineProperty(row, 'rowIndex', { //給每一行添加不可枚舉屬性rowIndex來標(biāo)識當(dāng)前行
value: rowIndex,
writable: true,
enumerable: false
})
},
handleSelectionChange(rows) {
this.selectionRow = rows //保存已選擇行
},
3. 按住ctrl
實(shí)現(xiàn)多選
首先要監(jiān)聽keydown
事件,以及keyup
事件,
methods: {
rowClick(row, column, event) {
let refsElTable = this.$refs.multipleTable; // 獲取表格對象
if (this.CtrlDown) {
refsElTable.toggleRowSelection(row); // ctrl多選 如果點(diǎn)擊兩次同樣會取消選中
return;
}
let findRow = this.selectionRow.find(c => c.rowIndex == row.rowIndex);
if (findRow ) {
refsElTable.toggleRowSelection(row, false);
return;
}
refsElTable.clearSelection();
refsElTable.toggleRowSelection(row); // 調(diào)用選中行方法
}地沮,
keyDown(event) {
let key = event.keyCode;
if (key == 17) this.CtrlDown = true;
},
keyUp(event) {
let key = event.keyCode;
if (key == 17) this.CtrlDown = false;
},
}嗜浮,
mounted() {
addEventListener("keydown", this.keyDown, false);
addEventListener("keyup", this.keyUp, false);
},
beforeDestroy() { //解綁
removeEventListener("keydown", this.keyDown);
removeEventListener("keyup", this.keyUp);
}
4. shift/alt
鍵實(shí)現(xiàn)連續(xù)多選
這一步要通過rowIndex
判斷已選擇的行中最上面和最下面的是哪行,再對比按住shift/alt
點(diǎn)擊的當(dāng)前行得到新的最上面和最下面的行摩疑,把這兩行中間的行進(jìn)行循環(huán)選中危融。
computed: { //實(shí)時(shí)得到最上行和最下行
bottomSelectionRow() {
if (this.selectionRow.length == 0) return null;
return this.selectionRow.reduce((start, end) => {
return start.rowIndex > end.rowIndex ? start : end;
});
},
topSelectionRow() {
if (this.selectionRow.length == 0) return null;
return this.selectionRow.reduce((start, end) => {
return start.rowIndex < end.rowIndex ? start : end;
});
}
},
methods: {
rowClick(row, column, event) {
let refsElTable = this.$refs.multipleTable; // 獲取表格對象
if (this.CtrlDown) {
refsElTable.toggleRowSelection(row); // ctrl多選 如果點(diǎn)擊兩次同樣會取消選中
return;
}
if ( this.shiftOrAltDown && this.selectionRow.length > 0) {
let topAndBottom = getTopAndBottom( row, this.bottomSelectionRow, this.topSelectionRow );
refsElTable.clearSelection(); //先清空 不然會導(dǎo)致在這兩行中間之外的行狀態(tài)不變
for (let index = topAndBottom.top; index <= topAndBottom.bottom; index++) { //選中兩行之間的所有行
refsElTable.toggleRowSelection(this.tableData[index], true);
}
} else {
let findRow = this.selectionRow.find(c => c.rowIndex == row.rowIndex); //找出當(dāng)前選中行
//如果只有一行且點(diǎn)擊的也是這一行則取消選擇 否則清空再選中當(dāng)前點(diǎn)擊行
if (findRow&& this.selectionRow.length === 1 ) {
refsElTable.toggleRowSelection(row, false);
return;
}
refsElTable.clearSelection();
refsElTable.toggleRowSelection(row);
}
},
rowStyle({row,rowIndex}) {
Object.defineProperty(row, 'rowIndex', { //給每一行添加不可枚舉屬性rowIndex來標(biāo)識當(dāng)前行
value: rowIndex,
writable: true,
enumerable: false
})
},
keyDown(event) {
let key = event.keyCode;
if (key == 17) this.CtrlDown = true;
if (key == 16 || key == 18) this.shiftOrAltDown = true;
},
keyUp(event) {
let key = event.keyCode;
if (key == 17) this.CtrlDown = false;
if (key == 16 || key == 18) this.shiftOrAltDown = false;
},
}雷袋,
mounted() {
addEventListener("keydown", this.keyDown, false);
addEventListener("keyup", this.keyUp, false);
},
beforeDestroy() { //解綁
removeEventListener("keydown", this.keyDown);
removeEventListener("keyup", this.keyUp);
}
/**獲取最新最上最下行 */
function getTopAndBottom(row, bottom, top) {
let n = row.rowIndex,
mx = bottom.rowIndex,
mi = top.rowIndex;
if (n > mx) {
return {
top: mi,
bottom: n
};
} else if (n < mx && n > mi) {
return {
top: mi,
bottom: n
};
} else if (n < mi) {
return {
top: n,
bottom: mx
};
} else if (n == mi || n == mx) {
return {
top: mi,
bottom: mx
};
}
};
5. 實(shí)現(xiàn)選中高亮
跟element-ui
本身的單選高亮實(shí)現(xiàn)方式一樣吉殃,都是給選中行加上current-row
這個(gè)class
類,所以要使用row-class-name
這個(gè)屬性(其實(shí)給每一行添加rowIndex
也可以用這個(gè)屬性)楷怒,判斷方式也是通過判斷rowIndex
對比
rowClassName({ row, rowIndex }) {
let rowName = "",
findRow = this.selectionRow.find(c => c.rowIndex === row.rowIndex);
if (findRow) {
rowName = "current-row "; // elementUI 默認(rèn)高亮行的class類 不用再樣式了^-^,也可通過css覆蓋改變背景顏色
}
return rowName; //也可以再加上其他類名 如果有需求的話
},