解决elementui table固定列的时候,滚动条被遮挡的问题(适用合计)

14 篇文章 0 订阅
14 篇文章 0 订阅
这篇博客介绍了在使用Element UI的表格组件时遇到的固定列滚动条无法拖动的问题。作者发现这是官方的一个bug,并分享了两种解决方案。方案一是通过设置CSS属性解决,但会导致部分样式丢失;方案二是自定义组件覆盖原组件,提供更灵活的滚动条样式设置。作者提供了详细的代码实现,并在main.js中引入自定义组件来覆盖原有的el-table。
摘要由CSDN通过智能技术生成

前段时间突然发现,当固定table列的时候,右侧的滚动条会被折腾,而不能拖动,上图

以前的时候固定列都是在右侧,也没有注意到这种问题,上次放到左侧,才发现拖不了了,上官方issues上找到了问题所在,官方的bug

支持设置chrome的滚动条,:barHeight='10',:barWidth='10'

方案一通过设置css属性.el-table__body-wrapper{z-index: 2}就可以了,但是有个小问题就是右侧浮动,中间的部分,失去了阴影,感觉没有分离开

https://github.com/ElemeFE/element/issues/20515

方案二

于是乎,根据提供的解决方案,覆盖了本地el-table组件

创建文件夹xTable
-index.vue

-xTable.js

index.vue文件

<!-- 解决table bug,固定fixed滚动条 -->
<!-- 如果出现问题的,可以使用xTable来解决 -->
<template>
  <div class="el-table"
       :class="[{
      'el-table--fit': fit,
      'el-table--striped': stripe,
      'el-table--border': border || isGroup,
      'el-table--hidden': isHidden,
      'el-table--group': isGroup,
      'el-table--fluid-height': maxHeight,
      'el-table--scrollable-x': layout.scrollX,
      'el-table--scrollable-y': layout.scrollY,
      'el-table--enable-row-hover': !store.states.isComplex,
      'el-table--enable-row-transition': (store.states.data || []).length !== 0 && (store.states.data || []).length < 100
    }, tableSize ? `el-table--${ tableSize }` : '']"
       @mouseleave="handleMouseLeave($event)">
    <div class="hidden-columns" ref="hiddenColumns">
      <slot></slot>
    </div>
    <div
      v-if="showHeader"
      v-mousewheel="handleHeaderFooterMousewheel"
      class="el-table__header-wrapper"
      ref="headerWrapper">
      <table-header
        ref="tableHeader"
        :store="store"
        :border="border"
        :default-sort="defaultSort"
        :style="{
          width: layout.bodyWidth ? layout.bodyWidth + 'px' : ''
        }">
      </table-header>
    </div>
    <div
      class="el-table__body-wrapper"
      ref="bodyWrapper"
      :class="[layout.scrollX ? `is-scrolling-${scrollPosition}` : 'is-scrolling-none']"
      :style="[bodyHeight,cssVars]">
      <table-body
        :context="context"
        :store="store"
        :stripe="stripe"
        :row-class-name="rowClassName"
        :row-style="rowStyle"
        :highlight="highlightCurrentRow"
        :style="{
           width: bodyWidth
        }">
      </table-body>
      <div
        v-if="!data || data.length === 0"
        class="el-table__empty-block"
        ref="emptyBlock"
        :style="emptyBlockStyle">
        <span class="el-table__empty-text">
        </span>
      </div>
      <div
        v-if="$slots.append"
        class="el-table__append-wrapper"
        ref="appendWrapper">
        <slot name="append"></slot>
      </div>
    </div>
    <div
      v-if="!data || data.length === 0"
      class="el-table__empty-block"
      ref="emptyBlock"
      :style="[bodyHeight, {
          position:'absolute',
          top: layout.headerHeight - (layout.scrollX ? scrollbarHeight : 0) + 'px'
        }]">
        <span class="el-table__empty-text">
          <slot name="empty">{{ emptyText || t('el.table.emptyText') }}</slot>
        </span>
    </div>
    <div
      v-if="showSummary"
      v-show="data && data.length > 0"
      v-mousewheel="handleHeaderFooterMousewheel"
      class="el-table__footer-wrapper"
      style="margin-top: 0px"
      ref="footerWrapper">
      <table-footer
        :store="store"
        :border="border"
        :sum-text="sumText || t('el.table.sumText')"
        :summary-method="summaryMethod"
        :default-sort="defaultSort"
        :style="{
          width: layout.bodyWidth ? layout.bodyWidth + 'px' : ''
        }">
      </table-footer>
    </div>
    <div
      v-if="fixedColumns.length > 0"
      v-mousewheel="handleFixedMousewheel"
      class="el-table__fixed"
      ref="fixedWrapper"
      :style="[{
        width: layout.fixedWidth ? layout.fixedWidth + 'px' : ''
      },
      fixedHeight]">
      <div
        v-if="showHeader"
        class="el-table__fixed-header-wrapper"
        ref="fixedHeaderWrapper">
        <table-header
          ref="fixedTableHeader"
          fixed="left"
          :border="border"
          :store="store"
          :style="{
            width: bodyWidth
          }"></table-header>
      </div>
      <div
        class="el-table__fixed-body-wrapper"
        ref="fixedBodyWrapper"
        :style="[{
          top: layout.headerHeight + 'px'
        },
        fixedBodyHeight]">
        <table-body
          fixed="left"
          :store="store"
          :stripe="stripe"
          :highlight="highlightCurrentRow"
          :row-class-name="rowClassName"
          :row-style="rowStyle"
          :style="{
            width: bodyWidth
          }">
        </table-body>
        <div
          v-if="$slots.append"
          class="el-table__append-gutter"
          :style="{ height: layout.appendHeight + 'px'}"></div>
      </div>
    </div>
    <div
      v-if="fixedColumns.length > 0 && showSummary"
      v-show="data && data.length > 0"
      class="el-table__fixed-footer-wrapper"
      ref="fixedFooterWrapper"
      :style="{
            width: layout.fixedWidth ? layout.fixedWidth + 'px' : '',
            overflow: 'hidden'
          }">
      <table-footer
        fixed="left"
        :border="border"
        :sum-text="sumText || t('el.table.sumText')"
        :summary-method="summaryMethod"
        :store="store"
        :style="{
            width: bodyWidth,
          }"></table-footer>
    </div>
    <div
      v-if="rightFixedColumns.length > 0"
      v-mousewheel="handleFixedMousewheel"
      class="el-table__fixed-right"
      ref="rightFixedWrapper"
      :style="[{
        width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '',
        right: layout.scrollY ? (border ? scrollbarWidth : (scrollbarWidth || 0)) + 'px' : ''
      },
      fixedHeight]">
      <div v-if="showHeader"
           class="el-table__fixed-header-wrapper"
           ref="rightFixedHeaderWrapper">
        <table-header
          ref="rightFixedTableHeader"
          fixed="right"
          :border="border"
          :store="store"
          :style="{
            width: bodyWidth
          }"></table-header>
      </div>
      <div
        class="el-table__fixed-body-wrapper"
        ref="rightFixedBodyWrapper"
        :style="[{
          top: layout.headerHeight + 'px'
        },
        fixedBodyHeight]">
        <table-body
          fixed="right"
          :store="store"
          :stripe="stripe"
          :row-class-name="rowClassName"
          :row-style="rowStyle"
          :highlight="highlightCurrentRow"
          :style="{
            width: bodyWidth
          }">
        </table-body>
        <div
          v-if="$slots.append"
          class="el-table__append-gutter"
          :style="{ height: layout.appendHeight + 'px' }"></div>
      </div>
    </div>
    <div
      v-if="rightFixedColumns.length > 0 && showSummary"
      v-show="data && data.length > 0"
      class="el-table__fixed-right"
      ref="fixedFooterWrapper"
      :style="{
            width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '',left: 'auto',top: 'auto',bottom: '0',
            right: layout.scrollY ? (border ? scrollbarWidth : (scrollbarWidth || 0)) + 'px' : 0,
            height: layout.footerHeight + 'px',
            overflow: 'hidden'
          }">
      <div
        class="el-table__fixed-footer-wrapper"
        ref="rightFixedFooterWrapper"
        :style="[{
        left: 'auto',
        right: layout.scrollY ? (border ? scrollbarWidth : (scrollbarWidth || 0)) + 'px' : 0
      }]">
        <table-footer
          fixed="right"
          :border="border"
          :sum-text="sumText || t('el.table.sumText')"
          :summary-method="summaryMethod"
          :store="store"
          :style="{
              width: bodyWidth
            }"></table-footer>
      </div>
    </div>
    <div
      v-if="rightFixedColumns.length > 0"
      class="el-table__fixed-right-patch"
      ref="rightFixedPatch"
      :style="{
        width: layout.scrollY ? scrollbarWidth + 'px' : '0',
        height: layout.headerHeight + 'px'
      }"></div>
    <div class="el-table__column-resize-proxy" ref="resizeProxy" v-show="resizeProxyVisible"></div>
  </div>
</template>
<script>
  import ELTable from 'element-ui/lib/table'

  export default {
    extends: ELTable,
    name: "XTable",
    props: {
      barHeight: {
        type: Number | String,// 滚动条高度
        default: 12
      },
      barWidth: {
        type: Number | String,// 滚动条宽度
        default: 11
      },
    },
    data() {
      return {
        redHeight: 1 // 如果滚动条设置的是谷歌改变的滚动条,那么差值设置为差量值
      }
    },
    watch: {
      data(v){
        if (v && v.length > 0) {
          if (this.fixedColumns.length > 0 && this.showSummary) {
            this.$nextTick().then(async () => {
              this.layout.updateElsHeight()
              await this.$nextTick()
              this.layout.updateElsHeight()
            })
          }
        }
      }
    },
    computed: {
      scrollbarHeight() {
        return this.layout.gutterWidth >= 17 ? this.layout.gutterWidth : this.barHeight
      },
      scrollbarWidth() {
        return this.layout.gutterWidth >= 17 ? this.layout.gutterWidth : this.barWidth
      },
      cssVars() {
        console.log(this.scrollbarHeight)
        console.log(this.scrollbarWidth)
        return {
          "--scrollbarHeight": this.scrollbarHeight + 'px',
          "--scrollbarWidth": this.scrollbarWidth + 'px'
        };
      },
      fixedBodyHeight() {
        if (this.height) {
          return {
            height: this.layout.fixedBodyHeight ? this.layout.fixedBodyHeight - (this.scrollbarHeight >= 17 ? 0 : this.scrollbarHeight) + 'px' : ''
          };
        } else if (this.maxHeight) {
          let maxHeight = parseHeight(this.maxHeight);
          if (typeof maxHeight === 'number') {
            maxHeight = this.layout.scrollX ? maxHeight - this.scrollbarHeight : maxHeight;
            if (this.showHeader) {
              maxHeight -= this.layout.headerHeight;
            }
            maxHeight -= this.layout.footerHeight;
            return {
              'max-height': maxHeight + 'px'
            };
          }
        }
        return {};
      },
      fixedHeight() {
        if (this.maxHeight) {
          if (this.showSummary) {
            return {
              height: this.layout.tableHeight ? this.layout.tableHeight - this.layout.footerHeight - (this.layout.scrollX ? this.scrollbarHeight : 0) - this.redHeight  + 'px' : ''
            }
          }
          return {
            bottom: this.layout.scrollX && this.data.length ? this.scrollbarHeight + 'px' : ''
          }
        } else {
          if (this.showSummary) {
            return {
              height: this.layout.tableHeight ? this.layout.tableHeight - this.layout.footerHeight - (this.layout.scrollX ? this.scrollbarHeight : 0) - this.redHeight  + 'px' : ''
            }
          }
          return {
            height: this.layout.scrollX ? 'auto' : this.layout.viewportHeight ? this.layout.viewportHeight + 'px' : '',
            bottom: this.layout.scrollX ? this.scrollbarHeight + 'px' : ''
          }
        }
      },
      bodyHeight() {
        const { headerHeight = 0, bodyHeight, footerHeight = 0} = this.layout;
        if (this.height) {
          if (this.showSummary) {
            return {
              height: this.layout.scrollX ? (bodyHeight ? bodyHeight - this.redHeight + 'px' : '') : bodyHeight ? bodyHeight + 'px' : ''
            }
          }
          return {
            height: bodyHeight ? bodyHeight + 'px' : ''
          };
        } else if (this.maxHeight) {
          const maxHeight = this.parseHeight(this.maxHeight);
          if (typeof maxHeight === 'number') {
            return {
              'max-height': (maxHeight - footerHeight - (this.showHeader ? headerHeight : 0) - this.redHeight) + 'px'
            };
          }
        }
        return {};
      },

    },
    methods: {
      parseHeight(height) {
        if (typeof height === 'number') {
          return height;
        }
        if (typeof height === 'string') {
          if (/^\d+(?:px)?$/.test(height)) {
            return parseInt(height, 10);
          } else {
            return height;
          }
        }
        return null;
      }
    }
  }
</script>
<style scoped lang="scss">
  .el-table__fixed-right::before, .el-table__fixed::before{
    height: 0!important;
  }
  .el-table ::v-deep{
    .el-table__body-wrapper::-webkit-scrollbar {
      height: var(--scrollbarHeight);
      width: var(--scrollbarWidth);
    }
  }
</style>

xTable.js文件

import XTableCom from '@/components/XTable/index'

const XTable = {
  install: function(Vue) {
    Vue.component('el-table', XTableCom) // 如果不想覆盖el-table的话,那就改成别的名称x-tbale
  }
}

export default XTable

在main.js引入组件

import xTable from '@/components/xTable/xTable.js'

// 引入组件
Vue.use(xTable)

原文链接 https://github.com/ElemeFE/element/pull/19716

这样就可以完全覆盖之前的el-table组件了

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值