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
          }
        }
posted @ 2020-11-06 14:53  卷叶小树  阅读(15486)  评论(8编辑  收藏  举报