解决element ui table组件多层固定列,子列内容遮挡

444 阅读1分钟

问题原因:elementUI table组件的开发者对固定列的宽度计算只计算到了第一层,所以当第一层的宽度小于其子级总宽度的时候就会导致内容被遮挡。(也不知道是不是table组件的开发者是不是故意为之...)

截屏2022-09-28 上午11.05.54.png

解决方案,重写updateColumnsWidth方法,基于原型替换默认的updateColumnsWidth方法;

实现代码:

import Vue from 'vue';
// 重写fxied固定逻辑,解决定宽内容遮挡
export default function updateColumnsWidth(){
  if (Vue.prototype.$isServer) return;
  const fit = this.fit;
  const bodyWidth = this.table.$el.clientWidth;
  let bodyMinWidth = 0;

  const flattenColumns = this.getFlattenColumns();
  let flexColumns = flattenColumns.filter((column) => typeof column.width !== 'number');

  flattenColumns.forEach((column) => {
    if (typeof column.width === 'number' && column.realWidth) column.realWidth = null;
  });

  if (flexColumns.length > 0 && fit) {
    flattenColumns.forEach((column) => {
      bodyMinWidth += column.width || column.minWidth || 80;
    });

    const scrollYWidth = this.scrollY ? this.gutterWidth : 0;

    if (bodyMinWidth <= bodyWidth - scrollYWidth) { // 不需要导航条
      this.scrollX = false;

      const totalFlexWidth = bodyWidth - scrollYWidth - bodyMinWidth;

      if (flexColumns.length === 1) {
        flexColumns[0].realWidth = (flexColumns[0].minWidth || 80) + totalFlexWidth;
      } else {
        const allColumnsWidth = flexColumns.reduce((prev, column) => prev + (column.minWidth || 80), 0);
        const flexWidthPerPixel = totalFlexWidth / allColumnsWidth;
        let noneFirstWidth = 0;

        flexColumns.forEach((column, index) => {
          if (index === 0) return;
          const flexWidth = Math.floor((column.minWidth || 80) * flexWidthPerPixel);
          noneFirstWidth += flexWidth;
          column.realWidth = (column.minWidth || 80) + flexWidth;
        });

        flexColumns[0].realWidth = (flexColumns[0].minWidth || 80) + totalFlexWidth - noneFirstWidth;
      }
    } else { // 需要导航条
      this.scrollX = true;
      flexColumns.forEach(function(column) {
        column.realWidth = column.minWidth;
      });
    }

    this.bodyWidth = Math.max(bodyMinWidth, bodyWidth);
    this.table.resizeState.width = this.bodyWidth;
  } else {
    flattenColumns.forEach((column) => {
      if (!column.width && !column.minWidth) {
        column.realWidth = 80;
      } else {
        column.realWidth = column.width || column.minWidth;
      }

      bodyMinWidth += column.realWidth;
    });
    this.scrollX = bodyMinWidth > bodyWidth;

    this.bodyWidth = bodyMinWidth;
  }

  const fixedColumns = this.store.states.fixedColumns;
  if (fixedColumns.length > 0) {
    this.fixedWidth = fixedWidthSun(fixedColumns)
  }
  const rightFixedColumns = this.store.states.rightFixedColumns;
  if (rightFixedColumns.length > 0) {
    let rightFixedWidth = 0;
    rightFixedColumns.forEach(function(column) {
      rightFixedWidth += column.realWidth || column.width;
    });

    this.rightFixedWidth = rightFixedWidth;
  }

  this.notifyObservers('columns');
}
// 计算固定列宽度
function fixedWidthSun(fixedColumns){
  let fixedWidth = 0;
  fixedColumns.forEach(function(column) {
    fixedWidth += column.children?fixedWidthSun(column.children):column.realWidth || column.width;
  });
  return fixedWidth
}

下篇:重写elementUi table,实现顶部固定合计行。