前幾天寫了一個(gè)關(guān)于 vxe-table 鼠標(biāo)滑動(dòng)選擇多行 的博客,在項(xiàng)目上線的過(guò)程中,發(fā)現(xiàn)這個(gè)功能還是有點(diǎn)bug,在經(jīng)過(guò)我對(duì)vxe-table pro版本 的演示后vxe-table PRO,認(rèn)真調(diào)試后,終于解決了bug,并且這個(gè)功能和pro版本可以說(shuō)是幾乎一模一樣。注意:我是說(shuō)這個(gè)滑動(dòng)選擇的功能,不是說(shuō)是pro版本的所有功能,哈哈哈。
我VUE用的是2.x版本.
如果是VUE是3版本,請(qǐng)參考下面這篇博客。
Vue3 vxe-table 手寫鼠標(biāo)區(qū)域選中-CSDN博客
下面是官網(wǎng)的pro版本示例
這是我的示例,是不是感覺一樣呢。demo?看在線演示。
?接下來(lái)我來(lái)展示我的實(shí)現(xiàn)方法。
先說(shuō)下思路吧:
1.鼠標(biāo)滑動(dòng)時(shí)顯示的那個(gè)框,實(shí)際上是一個(gè) div,所以需要定義div。
2.用戶進(jìn)行滑動(dòng)操作,肯定需要給表格添加鼠標(biāo)移動(dòng)監(jiān)聽事件。
3.用戶從什么時(shí)候位置開始移動(dòng)鼠標(biāo),什么時(shí)候結(jié)束移動(dòng)鼠標(biāo)。需要記錄那個(gè)框的開始位置和結(jié)束位置。
4.最后在用戶鼠標(biāo)移動(dòng)結(jié)束后,顯示這個(gè)框就行了。
開始實(shí)現(xiàn):
1.先來(lái)一個(gè)最基礎(chǔ)的vxe-grid表格,相信大家都清楚吧。
<template>
<div>
<!-- 注意這里的ref名稱,后續(xù)都會(huì)用到的 -->
<vxe-grid ref='xGrid' v-bind="gridOptions" height="400px">
</vxe-grid>
</div>
</template>
<script>
export default {
data() {
return{
gridOptions:{
//行配置,這里的行高一定需要指定
"row-config":{isCurrent:true,height:35},
//左上角按鈕
toolbarConfig:{
perfect: true,
enabled:true,
size:"mini",
buttons:[
{
code:'getcellselctdata',type:"text",name:'獲取選中數(shù)據(jù)'
}
],
},
//列配置 (使用列拖拽功能,必須配置useKey為true)
"column-config":{resizable:true,useKey:true},
//邊框
border:"full",
//斑馬紋
stripe:true,
//列信息
columns:[
{width:70,field:"id",title:"#",align:"left",fixed:"left"},
{width:100,field:"name",title:"姓名",align:"left",fixed:"left"},
{width:100,field:"age",title:"年齡",align:"left",fixed:"left"},
{width:100,field:"sex",title:"性別",align:"left"},
{width:100,field:"job",title:"崗位",align:"left"},
{width:270,field:"address",title:"地址",align:"left"},
],
//數(shù)據(jù)
data:[
{id:1,name:"張三",age:30,sex:"男",job:"前端",address:"中國(guó)xxxxxxxxxx"},
{id:2,name:"李四",age:30,sex:"男",job:"后端",address:"中國(guó)xxxxxxxxxx"},
{id:3,name:"王五",age:30,sex:"女",job:"運(yùn)維",address:"中國(guó)xxxxxxxxxx"},
{id:4,name:"趙六",age:30,sex:"男",job:"美工",address:"中國(guó)xxxxxxxxxx"},
{id:5,name:"老八",age:30,sex:"男",job:"項(xiàng)目經(jīng)理",address:"中國(guó)xxxxxxxxxx"},
{id:6,name:"桀桀",age:30,sex:"女",job:"售后",address:"中國(guó)xxxxxxxxxx"},
],
//這里一定要指定true,否則row-config的height沒用
'show-overflow':true,
//行配置,這里的行高一定需要指定
"row-config":{isCurrent:true,height:35,isHover:true},
},
}
},
mounted() {
},
methods: {
}
}
</script>
<style scoped>
</style>
顯示的效果是這樣的(下圖),并且滑動(dòng)選中是瀏覽器默認(rèn)的選中效果。
?2.清除瀏覽器的默認(rèn)選中行為:
.vxe-grid{
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
}
加上這個(gè)css代碼,這樣在鼠標(biāo)選中時(shí)就不會(huì)出現(xiàn)剛剛那個(gè)藍(lán)色的背景色了,這一步很重要哦。
需要全局的也可以寫到app.vue中。
3.定義div。也就是我所說(shuō)的框。并且在官網(wǎng)示例中也是這樣做的,大家可以放心。
我這里是定義了兩個(gè)框。分為非fixed和fixed區(qū)域的框。
<!-- 注意這里的ref名稱,后續(xù)都會(huì)用到的 -->
<!-- 正常區(qū)域的框 -->
<div class="vxe-table--cell-area" ref="cellarea">
<span class="vxe-table--cell-main-area"></span>
<span class="vxe-table--cell-active-area"></span>
</div>
<!-- 注意這里的ref名稱,后續(xù)都會(huì)用到的 -->
<!-- 左邊f(xié)ixed區(qū)域的框,右邊f(xié)ixed沒有嘗試過(guò)。。。 -->
<div class="vxe-table--cell-area" ref="fixedcellarea">
<span class="vxe-table--cell-main-area"></span>
<span class="vxe-table--cell-active-area"></span>
</div>
4.給表格添加監(jiān)聽(用戶鼠標(biāo)操作),記錄用戶鼠標(biāo)開始操作的位置和結(jié)束的位置。
在data中定義所需的變量,記錄用戶鼠標(biāo)滑動(dòng)開始位置和結(jié)束位置。
isSelecting: false, // 是否正在進(jìn)行選擇操作
selectionStart:{rowIndex:-1,cellIndex:-1}, // 選擇操作起始單元格位置
selectionEnd:{rowIndex:-1,cellIndex:-1}, // 選擇操作結(jié)束單元格位置
?然后給表格添加事件監(jiān)聽(這里的代碼不做過(guò)多的解釋,大家可以看看注釋):
methods里面是11個(gè)方法,在mounted里面調(diào)用addListener方法就歐克了。
?接下來(lái)給出這11個(gè)方法的代碼,有興趣的可以自己的需求進(jìn)行修改。
//返回table的ref名稱
getTablexGrid(){
return this.$refs.xGrid;
},
//添加事件
addListener(){
//添加多選列
this.$nextTick(()=>{
let tbody=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper table tbody");
if(tbody){
tbody.addEventListener("mousedown",this.tbodymousedown);
tbody.addEventListener("mouseup",this.tbodymouseup);
tbody.addEventListener("mousemove",this.tbodymousemove);
}
let bodyWrapper=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper");
if(bodyWrapper){
//注意這里的ref名稱,這里是非fixed區(qū)域的框的名稱
bodyWrapper.appendChild(this.$refs.cellarea);
}
setTimeout(()=>{
let fixedtbody=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper table tbody");
if(fixedtbody){
fixedtbody.addEventListener("mousedown",this.tbodymousedown);
fixedtbody.addEventListener("mouseup",this.tbodymouseup);
fixedtbody.addEventListener("mousemove",this.tbodymousemove);
}
let fixedBodyWrapper=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper");
if(fixedBodyWrapper){
//注意這里的ref名稱,這里是fixed區(qū)域的框的名稱
fixedBodyWrapper.appendChild(this.$refs.fixedcellarea);
}
})
})
},
//鼠標(biāo)按下事件
tbodymousedown(event){
//左鍵
if(event.button === 0){
// 記錄選擇操作起始位置
this.selectionStart = this.getCellPosition(event.target);
this.isSelecting = true;
}
},
//鼠標(biāo)移動(dòng)事件
tbodymousemove(event){
//左鍵
if(event.button === 0){
if (!this.isSelecting) return;
var x = event.clientX;
// 記錄選擇操作結(jié)束位置
this.selectionEnd = this.getCellPosition(event.target);
//設(shè)置樣式
this.setselectedCellArea();
//持續(xù)向右滾動(dòng)
var x = event.clientX;
var table=this.getTablexGrid().$el.querySelector(".vxe-table--body-wrapper table");
if(table){
let tableRect=table.parentElement.getBoundingClientRect();
if (x > tableRect.right - 20){
table.parentElement.scrollLeft+=20;
}
}
}
},
//鼠標(biāo)按鍵結(jié)束事件
tbodymouseup(event) {
//左鍵
if(event.button === 0){
this.isSelecting = false;
}
},
// 獲取單元格位置
getCellPosition(cell) {
try{
while(cell.tagName !== 'TD'){
cell = cell.parentElement;
}
// const rowIndex = cell.parentElement.rowIndex;
// const cellIndex = cell.cellIndex;
let visibleColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
const cellIndex = visibleColumn.findIndex((col)=>{
return col.id==cell.getAttribute("colid");
})
let visibleData=this.getTablexGrid().getTableData()["visibleData"];
const rowIndex =visibleData.findIndex((row)=>{
return row._X_ROW_KEY==cell.parentElement.getAttribute("rowid");
})
return { rowIndex, cellIndex };
}catch(e){
return { rowIndex:-1,cellIndex:-1};
}
},
//設(shè)置框打開
setselectedCellArea(){
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
let {width,height,left,top}=this.getAreaBoxPostion();
// .vxe-table--fixed-wrapper .vxe-table--body-wrapper
// .vxe-table--main-wrapper .vxe-table--body-wrapper
var activeElement=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-active-area");
var mainElement=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-main-area");
var fixedActiveElement=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-active-area");
var fixedMainElement=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-main-area");
//獲取固定列寬度f(wàn)ixed--hidden
var fixedWidth=0;
let flexDiv=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-left-wrapper");
if(flexDiv){
fixedWidth=flexDiv.offsetWidth;
}
var elements=[activeElement,mainElement,fixedActiveElement,fixedMainElement];
elements.forEach((element)=>{
if(element){
element.style.width=`${width}px`;
element.style.height=`${height}px`;
element.style.top=`${top}px`;
element.style.left=`${left}px`;
element.style.display="block";
}
})
this.openAreaBox();
this.selectionStart={"cellIndex":startColumnIndex,"rowIndex":startRowIndex};
this.selectionEnd={"cellIndex":endColumnIndex,"rowIndex":endRowIndex};
},
//根據(jù)開始位置和結(jié)束位置的索引計(jì)算框的width,height,left,top
getAreaBoxPostion(){
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
let visibleColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
let visibleData=this.getTablexGrid().getTableData()["visibleData"];
if(startColumnIndex<0||endColumnIndex<0||startRowIndex<0||endRowIndex<0)return;
var maxColumnIndex=visibleColumn.length-1;
var maxRowIndex=visibleData.length-1;
if(endColumnIndex>maxColumnIndex){
endColumnIndex=maxColumnIndex;
}
if(endRowIndex>maxRowIndex){
endRowIndex=maxRowIndex;
}
// height width left top display
// cellarea
let width=0,height=0,left=0,top=0;
let fixedwidth=0,fixedheight=0,fixedleft=0,fixedtop=0;
visibleColumn.forEach((col,index)=>{
if(index<startColumnIndex){
left+=this.getTablexGrid().getColumnWidth(col);
}
if(index<=endColumnIndex&&startColumnIndex<=index){
width+=this.getTablexGrid().getColumnWidth(col);
}
})
height=(endRowIndex-startRowIndex+1)*this.gridOptions["row-config"]["height"];
if(height<=0||width<=0){
this.destroyAreaBox();
return;
}
top=startRowIndex*this.gridOptions["row-config"]["height"];
return {width,height,left,top};
},
//顯示范圍框
openAreaBox(){
var element=this.$refs.xGrid.$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="block";
}
element=this.$refs.xGrid.$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="block";
}
},
//關(guān)閉范圍框
closeAreaBox(){
var element=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
element=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
},
//銷毀范圍框
destroyAreaBox(){
this.selectionStart={"rowIndex":-1,"cellIndex":-1};
this.selectionEnd={"rowIndex":-1,"cellIndex":-1};
var element=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
element=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
},
文章到這,就實(shí)現(xiàn)了功能哦。
5.但是需要在加一個(gè)功能,用戶點(diǎn)擊表格單元格時(shí)需要關(guān)閉原先的框,顯示用戶點(diǎn)擊單元格時(shí)的新框。這個(gè)可以說(shuō)的不是很清楚,但是在你們使用時(shí)就會(huì)發(fā)現(xiàn)這個(gè)問(wèn)題的。
?方法:
//表格單元格點(diǎn)擊事件
tableCellClick(e){
let {row,column}=e;
if(!this.isSelecting){
if(!this.lastActive||this.lastActive["rowid"]!=row["_X_ROW_KEY"]||this.lastActive["colid"]!=column["id"]){
this.selectionStart = this.getCellPosition(e.$event.target);
this.selectionEnd =this.selectionStart;
//設(shè)置樣式
this.setselectedCellArea();
this.lastActive={"rowid":"","colid":""};
}
}
},
6.那如何獲取選中區(qū)域的數(shù)據(jù)呢?相信這是大家比較關(guān)心的問(wèn)題吧。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-755215.html
console.log("是否正在進(jìn)行滑動(dòng)選中操作:",this.isSelecting);
//左上角坐標(biāo)
console.log("單元格起始位置:索引:",this.selectionStart);
//右下角坐標(biāo)
console.log("單元格結(jié)束位置:索引:",this.selectionEnd);
//這里需要是visibleData
let tableData=this.getTablexGrid().getTableData()["visibleData"];
let rowStart=this.selectionStart.rowIndex;
let rowEnd=this.selectionEnd.rowIndex;
let selectRows=tableData.filter((col,index)=>{
return rowStart<=index&&rowEnd>=index;
})
console.log("鼠標(biāo)選中行:",JSON.stringify(selectRows));
//這里需要是visibleColumn
let colStart=this.selectionStart.cellIndex;
let colEnd=this.selectionEnd.cellIndex;
let tableColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
let selectCols=tableColumn.filter((col,index)=>{
return colStart<=index&&colEnd>=index;
})
console.log("鼠標(biāo)選中列:",JSON.stringify(selectCols));
下面給出整個(gè)示例的完整代碼:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-755215.html
<template>
<div style="width: 600px;">
<!-- 正常區(qū)域的框 -->
<div class="vxe-table--cell-area" ref="cellarea">
<span class="vxe-table--cell-main-area"></span>
<span class="vxe-table--cell-active-area"></span>
</div>
<!-- 左邊f(xié)ixed區(qū)域的框,右邊f(xié)ixed沒有嘗試過(guò)。。。 -->
<div class="vxe-table--cell-area" ref="fixedcellarea">
<span class="vxe-table--cell-main-area"></span>
<span class="vxe-table--cell-active-area"></span>
</div>
<vxe-grid ref='xGrid' v-bind="gridOptions" height="400px"
@cell-click="tableCellClick"
@keydown="tableKeydown"
@toolbar-button-click="toolbarButtonClickEvent">
</vxe-grid>
</div>
</template>
<script>
import XEClipboard from 'xe-clipboard';
export default {
data() {
return{
gridOptions:{
"keyboard-config":{
isArrow: true,
},
//左上角按鈕
toolbarConfig:{
perfect: true,
enabled:true,
size:"mini",
buttons:[
{
code:'getcellselctdata',type:"text",name:'獲取選中數(shù)據(jù)(結(jié)果看控制臺(tái))'
}
],
},
//列配置 (使用列拖拽功能,必須配置useKey為true)
"column-config":{resizable:true,useKey:true},
//邊框
border:"full",
//斑馬紋
stripe:true,
//列信息
columns:[
{width:70,field:"id",title:"#",align:"left",fixed:"left"},
{width:100,field:"name",title:"姓名",align:"left",fixed:"left"},
{width:100,field:"age",title:"年齡",align:"left",fixed:"left"},
{width:100,field:"sex",title:"性別",align:"left"},
{width:100,field:"job",title:"崗位",align:"left"},
{width:270,field:"address",title:"地址",align:"left"},
],
//數(shù)據(jù)
data:[
{id:1,name:"張三",age:30,sex:"男",job:"前端",address:"中國(guó)xxxxxxxxxx"},
{id:2,name:"李四",age:30,sex:"男",job:"后端",address:"中國(guó)xxxxxxxxxx"},
{id:3,name:"王五",age:30,sex:"女",job:"運(yùn)維",address:"中國(guó)xxxxxxxxxx"},
{id:4,name:"趙六",age:30,sex:"男",job:"美工",address:"中國(guó)xxxxxxxxxx"},
{id:5,name:"老八",age:30,sex:"男",job:"項(xiàng)目經(jīng)理",address:"中國(guó)xxxxxxxxxx"},
{id:6,name:"桀桀",age:30,sex:"女",job:"售后",address:"中國(guó)xxxxxxxxxx"},
],
//這里一定要指定true,否則row-config的height沒用
'show-overflow':true,
//行配置,這里的行高一定需要指定
"row-config":{isCurrent:true,height:35,isHover:true},
},
//鼠標(biāo)滑動(dòng)選中
isSelecting: false, // 是否正在進(jìn)行選擇操作
selectionStart:{rowIndex:-1,cellIndex:-1}, // 選擇操作起始單元格位置
selectionEnd:{rowIndex:-1,cellIndex:-1}, // 選擇操作結(jié)束單元格位置
}
},
mounted() {
this.addListener();
},
methods: {
//返回table的ref名稱
getTablexGrid(){
return this.$refs.xGrid;
},
//添加事件
addListener(){
//添加多選列
this.$nextTick(()=>{
let tbody=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper table tbody");
if(tbody){
tbody.addEventListener("mousedown",this.tbodymousedown);
tbody.addEventListener("mouseup",this.tbodymouseup);
tbody.addEventListener("mousemove",this.tbodymousemove);
tbody.addEventListener("paste",this.tbodykeydown);
}
let bodyWrapper=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper");
if(bodyWrapper){
//注意這里的ref名稱,這里是非fixed區(qū)域的框的名稱
bodyWrapper.appendChild(this.$refs.cellarea);
}
setTimeout(()=>{
let fixedtbody=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper table tbody");
if(fixedtbody){
fixedtbody.addEventListener("mousedown",this.tbodymousedown);
fixedtbody.addEventListener("mouseup",this.tbodymouseup);
fixedtbody.addEventListener("mousemove",this.tbodymousemove);
fixedtbody.addEventListener("paste",this.tbodykeydown);
}
let fixedBodyWrapper=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper");
if(fixedBodyWrapper){
//注意這里的ref名稱,這里是fixed區(qū)域的框的名稱
fixedBodyWrapper.appendChild(this.$refs.fixedcellarea);
}
})
})
},
//鼠標(biāo)按下事件
tbodymousedown(event){
//左鍵
if(event.button === 0){
// 記錄選擇操作起始位置
this.selectionStart = this.getCellPosition(event.target);
this.isSelecting = true;
}
},
//鼠標(biāo)移動(dòng)事件
tbodymousemove(event){
//左鍵
if(event.button === 0){
if (!this.isSelecting) return;
var x = event.clientX;
// 記錄選擇操作結(jié)束位置
this.selectionEnd = this.getCellPosition(event.target);
//設(shè)置樣式
this.setselectedCellArea();
//持續(xù)向右滾動(dòng)
var x = event.clientX;
var table=this.getTablexGrid().$el.querySelector(".vxe-table--body-wrapper table");
if(table){
let tableRect=table.parentElement.getBoundingClientRect();
if (x > tableRect.right - 20){
table.parentElement.scrollLeft+=20;
}
}
}
},
//鼠標(biāo)按鍵結(jié)束事件
tbodymouseup(event) {
//左鍵
if(event.button === 0){
this.isSelecting = false;
}
},
// 獲取單元格位置
getCellPosition(cell) {
try{
while(cell.tagName !== 'TD'){
cell = cell.parentElement;
}
// const rowIndex = cell.parentElement.rowIndex;
// const cellIndex = cell.cellIndex;
let visibleColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
const cellIndex = visibleColumn.findIndex((col)=>{
return col.id==cell.getAttribute("colid");
})
let visibleData=this.getTablexGrid().getTableData()["visibleData"];
const rowIndex =visibleData.findIndex((row)=>{
return row._X_ROW_KEY==cell.parentElement.getAttribute("rowid");
})
return { rowIndex, cellIndex };
}catch(e){
return { rowIndex:-1,cellIndex:-1};
}
},
//設(shè)置框打開
setselectedCellArea(){
try{
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
let {width,height,left,top}=this.getAreaBoxPostion();
// .vxe-table--fixed-wrapper .vxe-table--body-wrapper
// .vxe-table--main-wrapper .vxe-table--body-wrapper
var activeElement=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-active-area");
var mainElement=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-main-area");
var fixedActiveElement=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-active-area");
var fixedMainElement=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-main-area");
//獲取固定列寬度f(wàn)ixed--hidden
var fixedWidth=0;
let flexDiv=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-left-wrapper");
if(flexDiv){
fixedWidth=flexDiv.offsetWidth;
}
var elements=[activeElement,mainElement,fixedActiveElement,fixedMainElement];
elements.forEach((element)=>{
if(element){
element.style.width=`${width}px`;
element.style.height=`${height}px`;
element.style.top=`${top}px`;
element.style.left=`${left}px`;
element.style.display="block";
}
})
this.openAreaBox();
this.selectionStart={"cellIndex":startColumnIndex,"rowIndex":startRowIndex};
this.selectionEnd={"cellIndex":endColumnIndex,"rowIndex":endRowIndex};
}catch(e){
}
},
//根據(jù)開始位置和結(jié)束位置的索引計(jì)算框的width,height,left,top
getAreaBoxPostion(){
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
let visibleColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
let visibleData=this.getTablexGrid().getTableData()["visibleData"];
if(startColumnIndex<0||endColumnIndex<0||startRowIndex<0||endRowIndex<0)return;
var maxColumnIndex=visibleColumn.length-1;
var maxRowIndex=visibleData.length-1;
if(endColumnIndex>maxColumnIndex){
endColumnIndex=maxColumnIndex;
}
if(endRowIndex>maxRowIndex){
endRowIndex=maxRowIndex;
}
// height width left top display
// cellarea
let width=0,height=0,left=0,top=0;
let fixedwidth=0,fixedheight=0,fixedleft=0,fixedtop=0;
visibleColumn.forEach((col,index)=>{
if(index<startColumnIndex){
left+=this.getTablexGrid().getColumnWidth(col);
}
if(index<=endColumnIndex&&startColumnIndex<=index){
width+=this.getTablexGrid().getColumnWidth(col);
}
})
height=(endRowIndex-startRowIndex+1)*this.gridOptions["row-config"]["height"];
if(height<=0||width<=0){
this.destroyAreaBox();
return;
}
top=startRowIndex*this.gridOptions["row-config"]["height"];
return {width,height,left,top};
},
//顯示范圍框
openAreaBox(){
var element=this.$refs.xGrid.$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="block";
}
element=this.$refs.xGrid.$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="block";
}
},
//關(guān)閉范圍框
closeAreaBox(){
var element=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
element=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="block";
}
},
//銷毀范圍框
destroyAreaBox(){
this.selectionStart={"rowIndex":-1,"cellIndex":-1};
this.selectionEnd={"rowIndex":-1,"cellIndex":-1};
var element=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
element=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-wrapper .vxe-table--body-wrapper .vxe-table--cell-area");
if(element){
element.style.display="none";
}
},
//表格單元格點(diǎn)擊事件
tableCellClick(e){
let {row,column}=e;
if(!this.isSelecting){
if(!this.lastActive||this.lastActive["rowid"]!=row["_X_ROW_KEY"]||this.lastActive["colid"]!=column["id"]){
this.selectionStart = this.getCellPosition(e.$event.target);
this.selectionEnd =this.selectionStart;
//設(shè)置樣式
this.setselectedCellArea();
this.lastActive={"rowid":"","colid":""};
}
}
},
toolbarButtonClickEvent({code,button}){
switch(code){
case "getcellselctdata":
//我給大家打印處理:
console.log("是否正在進(jìn)行滑動(dòng)選中操作:",this.isSelecting);
//左上角坐標(biāo)
console.log("單元格起始位置:索引:",this.selectionStart);
//右下角坐標(biāo)
console.log("單元格結(jié)束位置:索引:",this.selectionEnd);
//這里需要是visibleData
let tableData=this.getTablexGrid().getTableData()["visibleData"];
let rowStart=this.selectionStart.rowIndex;
let rowEnd=this.selectionEnd.rowIndex;
let selectRows=tableData.filter((col,index)=>{
return rowStart<=index&&rowEnd>=index;
})
console.log("鼠標(biāo)選中行:",JSON.stringify(selectRows));
//這里需要是visibleColumn
let colStart=this.selectionStart.cellIndex;
let colEnd=this.selectionEnd.cellIndex;
let tableColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
let selectCols=tableColumn.filter((col,index)=>{
return colStart<=index&&colEnd>=index;
})
console.log("鼠標(biāo)選中列:",JSON.stringify(selectCols));
break;
}
},
tableKeydown({$event}){
this.tbodykeydown($event);
},
tbodykeydown(event){
let tablexgrid=this.getTablexGrid();
let tableColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
let tableData=this.getTablexGrid().getTableData()["visibleData"];
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
var maxColumnIndex=tableColumn.length-1;
var maxRowIndex=tableData.length-1;
var minColumnIndex=0;
var minRowIndex=0;
if (event.ctrlKey && event.keyCode === 67) {
//ctrl+c 復(fù)制
this.contextMenuClickEvent({menu:{code:"cellCopy"}});
event.preventDefault();
}else if(event.ctrlKey&&event.keyCode === 86){
//ctrl+v 粘貼
this.contextMenuClickEvent({menu:{code:"cellPaste"}});
event.preventDefault();
}else if(event.ctrlKey && event.key === 'd'){
//ctrl+d
this.contextMenuClickEvent({menu:{code:"cellLineCopy"}});
event.preventDefault();
}else if(event.key === 'Delete'){
//delete
this.contextMenuClickEvent({menu:{code:"cellDelete"}});
event.preventDefault();
}else if(event.ctrlKey && event.key === 'x'){
//ctrl+x
this.contextMenuClickEvent({menu:{code:"cellCut"}});
event.preventDefault();
}else if(event.ctrlKey && event.key === 'z'){
//ctrl+z
this.contextMenuClickEvent({menu:{code:"cellSortValue"}});
event.preventDefault();
}else if(event.keyCode===39){
//右鍵 向右
if(endColumnIndex+1<=maxColumnIndex){
var currentRow=tablexgrid.getCurrentRecord();
const rowIndex =tableData.findIndex((row)=>{
return row._X_ROW_KEY==currentRow._X_ROW_KEY;
})
this.selectionStart={"cellIndex":endColumnIndex+1,"rowIndex":rowIndex};
this.selectionEnd={"cellIndex":endColumnIndex+1,"rowIndex":rowIndex};
}
this.setselectedCellArea();
this.tableScrollMove("right");
event.preventDefault();
}else if(event.keyCode===37){
//左鍵 向左
if(startColumnIndex-1>=minColumnIndex){
var currentRow=tablexgrid.getCurrentRecord();
const rowIndex =tableData.findIndex((row)=>{
return row._X_ROW_KEY==currentRow._X_ROW_KEY;
})
this.selectionStart={"cellIndex":startColumnIndex-1,"rowIndex":rowIndex};
this.selectionEnd={"cellIndex":startColumnIndex-1,"rowIndex":rowIndex};
}
this.setselectedCellArea();
this.tableScrollMove("left");
event.preventDefault();
}else if(event.keyCode===38){
//向上
var currentRow=tablexgrid.getCurrentRecord();
const rowIndex =tableData.findIndex((row)=>{
return row._X_ROW_KEY==currentRow._X_ROW_KEY;
})
if(rowIndex-1>=minRowIndex){
this.selectionStart={"cellIndex":startColumnIndex,"rowIndex":rowIndex-1};
this.selectionEnd={"cellIndex":startColumnIndex,"rowIndex":rowIndex-1};
}
this.setselectedCellArea();
//判斷是否小于最小行的個(gè)數(shù)
event.preventDefault();
}else if(event.keyCode===40){
//向下
var currentRow=tablexgrid.getCurrentRecord();
const rowIndex =tableData.findIndex((row)=>{
return row._X_ROW_KEY==currentRow._X_ROW_KEY;
})
if(rowIndex+1<=maxRowIndex){
this.selectionStart={"cellIndex":startColumnIndex,"rowIndex":rowIndex+1};
this.selectionEnd={"cellIndex":startColumnIndex,"rowIndex":rowIndex+1};
}
this.setselectedCellArea();
event.preventDefault();
}
},
//控制滾動(dòng)條,元素隱藏時(shí)滾動(dòng)條自動(dòng)滾動(dòng)到顯示的位置
//move:快捷鍵左右時(shí)有效,其他無(wú)效
tableScrollMove(move){
let tableColumn=this.getTablexGrid().getTableColumn()["visibleColumn"];
let tableData=this.getTablexGrid().getTableData()["visibleData"];
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
let fixedWidth=0;
//獲取固定列寬度f(wàn)ixed--hidden
let flexDiv=this.getTablexGrid().$el.querySelector(".vxe-table--fixed-left-wrapper");
if(flexDiv){
fixedWidth=flexDiv.offsetWidth;
}
//獲取td
var td;
var tbody=this.getTablexGrid().$el.querySelector(".vxe-table--main-wrapper table tbody");
if(tbody&&move=="left"){
var column=tableColumn[startColumnIndex];
td=tbody.querySelector(`td[colid="${column.id}"]`);
}else if(tbody&&move=="right"){
var column=tableColumn[endColumnIndex];
td=tbody.querySelector(`td[colid="${column.id}"]`);
}
if(td){
//判斷是否隱藏
var tdRect=td.getBoundingClientRect();
var table=this.getTablexGrid().$el.querySelector(".vxe-table--body-wrapper table");
if(table){
let tableRect=table.parentElement.getBoundingClientRect();
//需要減去左邊固定列的寬度
if (tdRect.top < tableRect.top ||tdRect.bottom > tableRect.bottom ||
tdRect.left < tableRect.left+fixedWidth ||tdRect.right > tableRect.right){
if(move=="right"){
table.parentElement.scrollLeft+=(tdRect.right-tableRect.right);
}else if(move=="left"){
table.parentElement.scrollLeft+=(tdRect.left-tableRect.left-fixedWidth);
}
} else {
// console.log("該 td 元素未隱藏");
}
}
}
},
//
contextMenuClickEvent({menu,row,column,rowIndex,columnIndex,$event}){
let startRowIndex=this.selectionStart["rowIndex"];
let endRowIndex=this.selectionEnd["rowIndex"];
let startColumnIndex=this.selectionStart["cellIndex"];
let endColumnIndex=this.selectionEnd["cellIndex"];
var tableColumn=JSON.parse(JSON.stringify(this.getTablexGrid().getTableColumn()["visibleColumn"]));
var tableData=this.getTablexGrid().getTableData()["visibleData"];
switch(menu.code){
//復(fù)制
case "cellCopy":
let enterStr="\r\n";
let spaceStr="\t";
let data=[];
for(var i=startRowIndex;i<=endRowIndex;i++){
let value=[];
for(var j=startColumnIndex;j<=endColumnIndex;j++){
value.push(tableData[i][tableColumn[j].field]);
}
data.push(value);
}
let finalStr=data.map((value)=>{
return value.join(spaceStr);
}).join(enterStr);
this.copyValue(finalStr);
break;
//粘貼
case "cellPaste":
navigator.clipboard.readText().then((text)=>{
if(text){
//去除首尾換行
text=text.replace(/^\r\n+|\r\n+$/g, '');
var snsArr=text.split(/\r\n+/);
var tArr=snsArr.map((value)=>{
return value.split("\t");
})
for(var i=0;i<tArr.length;i++){
let line=tArr[i];
if(startRowIndex+i>tableData.length-1)break;
let row=tableData[startRowIndex+i];
for(var j=0;j<line.length;j++){
if(startColumnIndex+j>tableColumn.length)break;
let column=tableColumn[startColumnIndex+j];
row[column.field]=line[j];
}
}
}
})
break;
//delete清除
case "cellDelete":
for(var i=startRowIndex;i<=endRowIndex;i++){
if(i>tableData.length-1)break;
for(var j=startColumnIndex;j<=endColumnIndex;j++){
if(j>tableColumn.length-1)break;
let row=tableData[i];
let column=tableColumn[j];
this.getTablexGrid().clearData(row,column.property);
}
}
break;
case "cellLineCopy":
//第一行的值不變,后面的行等于第一行的值
var firstRow=tableData[startRowIndex];
for(var i=startRowIndex+1;i<=endRowIndex;i++){
if(i>tableData.length-1)break;
for(var j=startColumnIndex;j<=endColumnIndex;j++){
if(j>tableColumn.length-1)break;
tableData[i][tableColumn[j].field]=firstRow[tableColumn[j].field];
}
}
break;
case "cellCut":
//剪切
this.contextMenuClickEvent({menu:{code:"cellCopy"}});
this.contextMenuClickEvent({menu:{code:"cellDelete"}});
break;
case "cellSortValue":
//自增
var firstRow=tableData[startRowIndex];
for(var i=startRowIndex+1;i<=endRowIndex;i++){
if(i>tableData.length-1)break;
for(var j=startColumnIndex;j<=endColumnIndex;j++){
if(j>tableColumn.length-1)break;
let value=firstRow[tableColumn[j].field];
if(!value)break;
if(!isNaN(value)){
tableData[i][tableColumn[j].field]=parseFloat(value)+(i-startRowIndex);
}else{
//最后一個(gè)字符
let lastChar=value[value.length-1];
//去除最后一個(gè)字符
let nvalChar=value.slice(0, -1);
if(/[a-zA-Z]/.test(lastChar)){
let result =this.generateAlphabetChars(lastChar,i-startRowIndex+1);
tableData[i][tableColumn[j].field]=nvalChar+result;
}
}
}
}
break;
}
},
//數(shù)據(jù)自增的工具方法
generateAlphabetChars(c, shift){
/**
* 將一個(gè)字符按照指定的偏移量進(jìn)行移位
* @param {string} c 需要移位的字符
* @param {number} shift 移位的偏移量
* @returns {string} 移位后的字符
*/
// 將字符轉(zhuǎn)換為 ASCII 碼
var asciiCode = c.charCodeAt(0);
// 計(jì)算移位后的 ASCII 碼
var shiftedAsciiCode = asciiCode + shift;
let flag = false;
if (shiftedAsciiCode > 122) {
shiftedAsciiCode -= 26;
} else if (shiftedAsciiCode < 97) {
shiftedAsciiCode += 26;
}
// 將 ASCII 碼轉(zhuǎn)換為字符
const shiftedChar = String.fromCharCode(shiftedAsciiCode);
return asciiCode + shift > 122 ? 'a' + shiftedChar: shiftedChar;
},
//復(fù)制的工具方法
copyValue(value){
if (XEClipboard.copy(value)) {
this.$VXETable.modal.message({content: '已復(fù)制到剪貼板!',status:'success',duration:400});
}
},
}
}
</script>
<style scoped>
.vxe-grid{
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
}
</style>
到了這里,關(guān)于vxe-table 鼠標(biāo)滑動(dòng)選擇多行,鼠標(biāo)區(qū)域選中批量操作[2]的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!