elementUi的el-table横向滚动条始终位于可视区域
问题场景
因为表格的列数多,所以table必然会出现横向滚动条。当行数过多时,出现纵向滚动条,操作时,就需要先滚动到表格底部,然后进行左右的拉动,这样是用户操作很不方便。
应对方案
当数据过多,table的X轴滚动条不在可视区域时,给table的父级容器添加一个滚动条perfectScrollbar,然后将perfectScrollbar的scroll值赋值给table自己的滚动条
代码实现
(1).tableDemo.vue
<template>
<div>
<el-row type="flex" justify="end">
<el-col :span="6">
<el-button type="primary" @click="getData">获取数据</el-button>
</el-col>
</el-row>
<div class="tableC" style="position: relative; ">
<!--绑定v-perfect-scrollbar 指令-->
<el-table
v-perfect-scrollbar
border
resizable
:data="tableData">
<el-table-column sortable="custom" prop="column_1" label="行1" show-overflow-tooltip="" width="120">
<template slot-scope="scope">
<span>{{ scope.row.column_1 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_2" label="行2" show-overflow-tooltip="" width="120">
<template slot-scope="scope">
<span>{{ scope.row.column_2 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_3" label="行3" show-overflow-tooltip="" width="140">
<template slot-scope="scope">
<span>{{ scope.row.column_3 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_4" label="行4" show-overflow-tooltip="" width="160">
<template slot-scope="scope">
<span>{{ scope.row.column_4 }}</span></template>
</el-table-column>
<el-table-column sortable="" prop="column_5" label="行5" show-overflow-tooltip="" width="180">
<template slot-scope="scope">
<span>{{ scope.row.column_5 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_6" label="行6" show-overflow-tooltip="" width="200">
<template slot-scope="scope">
<span>{{ scope.row.column_6 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_7" label="行7" show-overflow-tooltip="" width="220">
<template slot-scope="scope">
<span>{{ scope.row.column_7 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_8" label="行8" show-overflow-tooltip="" width="200">
<template slot-scope="scope">
<span>{{ scope.row.column_8 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_9" label="行9" show-overflow-tooltip="" width="200">
<template slot-scope="scope">
<span>{{ scope.row.column_9 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_10" label="行10" show-overflow-tooltip="" width="200">
<template slot-scope="scope">
<span>{{ scope.row.column_10 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_11" label="行11" show-overflow-tooltip="" width="200">
<template slot-scope="scope">
<span>{{ scope.row.column_11 }}</span>
</template>
</el-table-column>
<el-table-column sortable="" prop="column_12" label="行12" show-overflow-tooltip="" width="200">
<template slot-scope="scope">
<span>{{ scope.row.column_12 }}</span>
</template>
</el-table-column>
</el-table>
</div>
<!--用来占位-->
<el-pagination background="" layout="prev, pager, next" :total="1000"></el-pagination>
</div>
</template>
<script>
export
default {
data() {
return {
tableData:[]
}
},
methods: {
getData() {
var len = this.tableData.length
var i = 0;
while (i < 50) {
var bz = len + i;
this.tableData.push({
column_1: "第1-" + bz + "行的数据",
column_2: "第2-" + bz + "行的数据",
column_3: "第3-" + bz + "行的数据",
column_4: "第4-" + bz + "行的数据",
column_5: "第5-" + bz + "行的数据",
column_6: "第6-" + bz + "行的数据",
column_7: "第7-" + bz + "行的数据",
column_8: "第8-" + bz + "行的数据",
column_9: "第9-" + bz + "行的数据",
column_10: "第10-" + bz + "行的数据",
column_11: "第11" + bz + "行的数据",
column_12: "第12-" + bz + "行的数据",
});
i++;
}
},
},
};
</script>
<style scoped>
.el-row{ margin-bottom: 15px; }
.el-pagination{ margin-top: 20px; }
</style>
<!--需设置为全局css样式-->
<style>
.tableC{ position:relative;}
.el-table th{ height: 60px; }
.el-table td{ padding:0; height: 50px; font-size: 14px; }
.el-table.hide-scrollBar{
/*隐藏滚动条 设置底部padding20px*/
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE 10+ */
padding-bottom: 20px;
}
.el-table.hide-scrollBar ::-webkit-scrollbar { display: none; /* Chrome Safari */ }
</style>
<!--tableDemo.vue--end-->
(2).app.vue里面id="app"的div绑定v-app-scroll 指令,设置style="height: 100vh;overflow-y: scroll"
(3).directive.js
// 自定义table水平滚动条始终显示在可视区域
Vue.directive('perfectScrollbar', {
componentUpdated:function (el, binding,vnode) {
let trCount=vnode.context.tableData.length;// tr的个数
fixTabScrollbar(el,null,trCount)
}
})
//自定义app滚动事件
Vue.directive('appScroll', {
bind: function(el, binding, vNode) {
let start = (e) =>{
fixTabScrollbar(null,el)
}
// 添加事件监听器
el.addEventListener("scroll", start);
}
})
//app滚动->定位table的水平滚动条
function fixTabScrollbar(tabEle,appEle,trCount) {
var tabEle=tabEle||document.getElementsByClassName('el-table')[0] // table 元素
var appEle=appEle||document.getElementById("app") // 滚动条所在容器
if(!(tabEle&&appEle)) return;
var tabContainer=tabEle.parentNode; // table 的父级容器
let thead = tabEle.getElementsByClassName('el-table__header-wrapper')[0];
let tbody = tabEle.getElementsByClassName('el-table__body-wrapper')[0];
var trCount=trCount||tbody.getElementsByTagName("tr").length //tr的个数
let trHeight=50.4 //tr的高度(自己设置的,这里el-table-column需要设置为 show-overflow-tooltip,不然换行会影响tr的高度) elementui这个框架,不知道0.4哪里来的
let theadHeight=thead.clientHeight?thead.clientHeight:60; // 表头的高度,60是默认的高度(自己设置的)
let tabHeight=theadHeight+trHeight*trCount+18 //table的高度 (18是el-table水平滚动条的高度)
let tabWinWidth=thead.clientWidth //table视口的宽度
let tabWidth=thead.getElementsByTagName('table')[0].offsetWidth;//table的宽度
let appHeight=appEle.offsetHeight- getOffsetTop(appEle) // 窗口的高度
let tabOffsetTop=getOffsetTop(tabContainer) //table 距离顶部距离
let appScrollTop=appEle.scrollTop // 容器向上滚动的距离
let bottom=tabOffsetTop+tabHeight-appScrollTop-appHeight;
if(bottom>0&&tabWidth>tabWinWidth){ //底部大于0并且table的宽度大于el-table视口的宽度-->显示滚动条,并隐藏自己的滚动条
let scrollBarEle=null
let childEle=null
tabEle.classList.add("hide-scrollBar") //隐藏tableC自己的滚动条
if(document.getElementById('perfectScrollbar-div')==null){
scrollBarEle = document.createElement('div');
scrollBarEle.id = 'perfectScrollbar-div';
childEle=document.createElement('p');
childEle.id = 'perfectScrollbar-child';
tabContainer.appendChild(scrollBarEle);
scrollBarEle.appendChild(childEle);
scrollBarEle.style.display="block";
childEle.style.width=tabWidth+"px";
childEle.style.height="1px";
childEle.style.padding="0";
childEle.style.margin="0";
scrollBarEle.style.position="absolute";
scrollBarEle.style.overflowX="auto";
scrollBarEle.style.left="0px";
scrollBarEle.style.right="0px";
scrollBarEle.style.margin="auto";
}else{
scrollBarEle = document.getElementById('perfectScrollbar-div');
}
scrollBarEle.style.bottom=bottom+"px";
scrollBarEle.onscroll = function(){
let target=event.target;
let scrollLeft=target.scrollLeft
tbody.scrollLeft=scrollLeft;
}
}else{
tabEle.classList.remove("hide-scrollBar") //显示tableC自己的滚动条
var scrollBarEle=document.getElementById('perfectScrollbar-div');
if(scrollBarEle)scrollBarEle.parentNode.removeChild(scrollBarEle);
}
}
function getOffsetTop(obj) {
if (!!window.ActiveXObject || "ActiveXObject" in window) {
var y = obj.offsetTop;
while (obj = obj.offsetParent) y += obj.offsetTop;
return y;
}else{
return obj.offsetTop
}
}