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)
}
}
}