重写elementui Table实现合计行置顶、记录滚动条位置,且解决多行表头固定问题

1,311 阅读1分钟
  <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 v-if="showSummary && summaryTop" v-show="data && data.length > 0" v-mousewheel="handleHeaderFooterMousewheel"
      class="el-table__footer-wrapper" 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 class="el-table__body-wrapper" ref="bodyWrapper"
      :class="[layout.scrollX ? `is-scrolling-${scrollPosition}` : 'is-scrolling-none']" :style="[bodyHeight]">
      <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">
          <slot name="empty">{{ emptyText || t('el.table.emptyText') }}</slot>
        </span>
      </div>
      <div v-if="$slots.append" class="el-table__append-wrapper" ref="appendWrapper">
        <slot name="append"></slot>
      </div>
    </div>
    <div v-if="showSummary && !summaryTop" v-show="data && data.length > 0" v-mousewheel="handleHeaderFooterMousewheel"
      class="el-table__footer-wrapper" 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+ (summaryTop?layout.footerHeight:0) + '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 v-if="showSummary" v-show="data && data.length > 0" class="el-table__fixed-footer-wrapper"
        ref="fixedFooterWrapper" :style="summaryTop?{
          top: layout.headerHeight - 1 + 'px',
          bottom:'auto'
        }:{}">
        <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>
    <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 ? layout.gutterWidth : (layout.gutterWidth || 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+ (summaryTop?layout.footerHeight:0) + '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 v-if="showSummary" v-show="data && data.length > 0" class="el-table__fixed-footer-wrapper"
        ref="rightFixedFooterWrapper" :style="summaryTop?{
          top: layout.headerHeight - 1 + 'px'
        }:{}">
        <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 ? layout.gutterWidth + 'px' : '0',
      height: layout.headerHeight + 'px'
    }"></div>
    <div class="el-table__column-resize-proxy" ref="resizeProxy" v-show="resizeProxyVisible"></div>
  </div>
</template>
<script>
import { Table } from 'element-ui'
import updateColumnsWidth  from './updateColumnsWidth'
export default {
  name: 'RewriteTable',
  data:function (){
    return {
      scrollObj: {
        left: 0,
        top: 0
      }
    }
  },
  props: {
    //新增入参summary-top,合计行是否置顶
    summaryTop: {
      type: Boolean,
      default: false
    }
  },
  extends: Table,
  methods: {
    //利用vue的混入模式重写rewritePosition方法,实现记录table表格滚动条位置
    rewritePosition (type) {
        const { scrollLeft, scrollTop, offsetWidth, scrollWidth } = this.bodyWrapper;
        const { headerWrapper, footerWrapper, fixedBodyWrapper, rightFixedBodyWrapper } = this.$refs;
        const left = type ? this.scrollObj.left : scrollLeft;
        const top =  type ? this.scrollObj.top : scrollTop;
        if (headerWrapper) headerWrapper.scrollLeft = left;
        if (footerWrapper) footerWrapper.scrollLeft = left;
        if (fixedBodyWrapper) fixedBodyWrapper.scrollTop =  top;
        if(!type){
          this.scrollObj.left = left
          this.scrollObj.top = top
        }else{
          this.bodyWrapper.scrollLeft = left
          this.bodyWrapper.scrollTop = top
        }
        if (rightFixedBodyWrapper) rightFixedBodyWrapper.scrollTop = top;
        const maxScrollLeftPosition = scrollWidth - offsetWidth - 1;
        if (scrollLeft >= maxScrollLeftPosition) {
          this.scrollPosition = 'right';
        } else if (scrollLeft === 0) {
          this.scrollPosition = 'left';
        } else {
          this.scrollPosition = 'middle';
        }
    },
    syncPostion() {
       this.rewritePosition()
    }
  },
  created() {
    //重写 Layout构造函数的updateColumnsWidth方法,解决多行表头固定问题
    //updateColumnsWidth方法上篇文章有记录代码
    this.layout.updateColumnsWidth = updateColumnsWidth
  },
  activated() {
    this.rewritePosition(true)
  }
}
</script>