el table header adaptively solves header misalignment and fixed column misalignment perfectly according to content

  • 2021-10-16 00:56:38
  • OfStack

You can use it by copying the code into an instruction. Called by instruction. (Usage < el-table v-tableFit > < /el-table > )

The header is set by calculating the width of the text, and other contents cannot be calculated.

More than 5000 cells are used according to the actual situation, because the more cells, the longer the calculation time.

Try to use v-if, otherwise there will be calculation errors in some cases.


Vue.directive("tableFit", {
 // Object of the component where the instruction is located  VNode  And its son  VNode  Called after all updates. 
 componentUpdated(el, binding, vnode) {
  setTimeout(() => {
   adjustColumnWidth(el, vnode);
  }, 0)
 },
});

function adjustColumnWidth(table, vnode) {
 // Chinese and full-angle regularity 
 const CN = new RegExp("[\u4E00-\u9FA5]|[^\uFF00-\uFFFF]");
 const NUM = new RegExp("[0-9]");
 // Pixel width ratio of Chinese fonts 
 const CN_RATE = 1.1
 // Pixel width ratio of digital fonts 
 const NUM_RATE = 0.65
 // Pixel width ratio of other fonts 
 const OTHER_RATE = 0.5
 
 const columns = vnode.child.columns.slice()
 //el-table Pass colgroup Label settings html Width 
 const colgroup = table.querySelector("colgroup");
 const colDefs = [...colgroup.querySelectorAll("col")];
 // Ignore   Width is set   Serial number   Multiple check boxes   Columns of 
 // Judge gutter Does it already exist 
 const gutter = colgroup.querySelector(`col[name=gutter]`)
 const gutterx = colgroup.querySelector(`col[name=gutterx]`)
 let except = 0
 if (gutter || gutterx) {
  // Delete gutter
  colDefs.pop()
 }
 // If order number   Multiple check boxes are deleted 
 except = colDefs.length - columns.length
 colDefs.splice(0, except)
 for (let i = columns.length - 1; i >= 0; i--) {
  if (columns[i].width) {
   colDefs.splice(i, 1)
   columns.splice(i, 1)
  }
 }

 // Set the width per column 
 colDefs.forEach((col, index) => {
  //colgroup Medium   And   The of the header label class Same name   Pass class Find the same column 
  const clsName = col.getAttribute("name");
  const cells = [
   ...table.querySelectorAll(`.el-table__body-wrapper td.${clsName}`),
   ...table.querySelectorAll(`th.${clsName}`),
  ];
  const widthList = cells.map((el) => {
   const cell = el.querySelector(".cell")
   if (cell) {
    let fontSize = parseInt(window.getComputedStyle(cell,null).fontSize)
    fontSize = fontSize ? fontSize : 14
    let width = 0
    // Calculate the width of each character 
    for(let str of cell.innerText) {
     if(CN.test(str)) {
      width += fontSize * CN_RATE
     }else if(NUM.test(str)) {
      width += fontSize * NUM_RATE
     }else {
      width += fontSize * OTHER_RATE
     }
    }
    return Math.ceil(width)
   } else {
    return 0
   }
  });
  
  // Take 1 Maximum width in a column 
  const max = Math.max(...widthList);
  if (max !== 0) {
   // Set in table data minWidth  Recalculate the original width to prevent dimensional changes 
   //20 + 2  20  Yes cell Class padding 2  Is to give extra space 
   columns[index].minWidth = max + 22
   table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => {
    el.setAttribute("width", max + 22);
   });
  }
 });

 // Called after setting el-table Method to update the layout 
 vnode.child.doLayout()

 tableRevise(table)
}

Correct table header and fixed column dislocation

If there is no dislocation, it can be ignored


// Amendment el-table Dislocation 
function tableRevise(table) {
 const tableWrapper = table.querySelector('.el-table__body-wrapper')
 const tableBody = table.querySelector('.el-table__body')
 const colgroup = table.querySelector("colgroup");
 /**
  * ( The following values are the height of the scroll bar, which can be passed by yourself according to the situation class Revise )
  */
 // When the content is larger than the container 
 if (tableBody.clientWidth > tableWrapper.offsetWidth) {
  
  // Settings x Axial rolling 
  tableWrapper.style.overflowX = 'auto'
  // Resolve fixed column misalignment   (If there is no dislocation, the following can be ignored) 
  let fixedWrap = table.querySelectorAll('.el-table .el-table__fixed-body-wrapper')
  if (fixedWrap.length > 0) {
   fixedWrap.forEach(item => {
    item.style.paddingBottom = 8 + 'px'
   })
  }
  // Resolve fixed column override scroll bar 
  let fixed_left = table.querySelector('.el-table .el-table__fixed')
  let fixed_right = table.querySelector('.el-table .el-table__fixed-right')
  if (fixed_left) {
   fixed_left.style.height = 'calc(100% - 8px)'
  }
  if (fixed_right) {
   fixed_right.style.height = 'calc(100% - 8px)'
  }
  // Solve the offset of meter header 
  // There is no native gutter Add it yourself when you are 1 A 
  const gutter = colgroup.querySelector(`col[name=gutter]`)
  const gutterx = colgroup.querySelector(`col[name=gutterx]`)
  if (!gutter && !gutterx) {
   let col = document.createElement('col')
   col.setAttribute('name', 'gutterx')
   col.setAttribute('width', '8')
   colgroup.appendChild(col)
  }
 }
}


Related articles: