Element分析(工具篇)——TableLayout

说明 【Element分析(工具篇)——TableLayout】table-layout是对整个表格宽高等布局进行修改的。
源码解读

import scrollbarWidth from 'element-ui/src/utils/scrollbar-width'; class TableLayout { constructor(options) { this.table = null; this.store = null; this.columns = null; this.fit = true; this.showHeader = true; this.height = null; this.scrollX = false; this.scrollY = false; this.bodyWidth = null; this.fixedWidth = null; this.rightFixedWidth = null; this.tableHeight = null; this.headerHeight = 44; // 表头高度 this.viewportHeight = null; // 表格高度 - 滚动条的高度 this.bodyHeight = null; // 表格高度 - 表头高度 this.fixedBodyHeight = null; // 表格高度 - 表头高度 - 滚动条高度 this.gutterWidth = scrollbarWidth(); // 滚动条宽度for (let name in options) { if (options.hasOwnProperty(name)) { this[name] = options[name]; } }if (!this.table) { throw new Error('table is required for Table Layout'); } if (!this.store) { throw new Error('store is required for Table Layout'); } }/** * 更新 scrollY */ updateScrollY() { const height = this.height; if (typeof height !== 'string' && typeof height !== 'number') return; const bodyWrapper = this.table.bodyWrapper; if (this.table.$el && bodyWrapper) { const body = bodyWrapper.querySelector('.el-table__body'); this.scrollY = body.offsetHeight > bodyWrapper.offsetHeight; } }/** * 设置高度 * @param value 高度值 * @param prop 设置的属性名 */ setHeight(value, prop = 'height') { const el = this.table.$el; if (typeof value =https://www.it610.com/article/=='string' && /^\d+$/.test(value)) { value = Number(value); }this.height = value; if (!el) return; // 没有挂载的的 DOM if (typeof value =https://www.it610.com/article/=='number') { el.style[prop] = value + 'px'; this.updateHeight(); } else if (typeof value =https://www.it610.com/article/=='string') { this.updateHeight(); } }/** * 设置最高高度 * @param value 高度值 * @returns {*} */ setMaxHeight(value) { return this.setHeight(value, 'max-height'); }/** * 更新高度 */ updateHeight() { const height = this.tableHeight = this.table.$el.clientHeight; const noData = https://www.it610.com/article/!this.table.data || this.table.data.length === 0; const { headerWrapper } = this.table.$refs; if (this.showHeader && !headerWrapper) return; // 如果要显示 header,却没 headerWrapper if (!this.showHeader) {// 如果不显示表头 this.headerHeight = 0; // 表头高度为 0 if (this.height !== null && (!isNaN(this.height) || typeof this.height ==='string')) { this.bodyHeight = height; // 说明表的主体部分充斥了整个表格 } // 固定表体的高度 this.fixedBodyHeight = this.scrollX ? height - this.gutterWidth : height; } else {// 如果显示表头 const headerHeight = this.headerHeight = headerWrapper.offsetHeight; const bodyHeight = height - headerHeight; if (this.height !== null && (!isNaN(this.height) || typeof this.height === 'string')) { this.bodyHeight = bodyHeight; } this.fixedBodyHeight = this.scrollX ? bodyHeight - this.gutterWidth : bodyHeight; } this.viewportHeight = this.scrollX ? height - (noData ? 0 : this.gutterWidth) : height; }/** * 更新 */ update() { const fit = this.fit; const columns = this.table.columns; const bodyWidth = this.table.$el.clientWidth; let bodyMinWidth = 0; const flattenColumns = []; columns.forEach((column) => { if (column.isColumnGroup) {// 如果是列组,就放入其包含的列 flattenColumns.push.apply(flattenColumns, column.columns); } else { flattenColumns.push(column); } }); // 自适应的列 let flexColumns = flattenColumns.filter((column) => typeof column.width !== 'number'); // 如果有自适应的列,并且规定了自适应 if (flexColumns.length > 0 && fit) { flattenColumns.forEach((column) => { bodyMinWidth += column.width || column.minWidth || 80; }); if (bodyMinWidth < bodyWidth - this.gutterWidth) { // DON'T HAVE SCROLL BAR 没有滚动条 this.scrollX = false; // 没有横向滚动条const totalFlexWidth = bodyWidth - this.gutterWidth - 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 { // HAVE HORIZONTAL SCROLL BAR 如果有垂直滚动条 this.scrollX = true; flexColumns.forEach(function(column) { column.realWidth = column.minWidth; }); }this.bodyWidth = Math.max(bodyMinWidth, bodyWidth); } else {// 如果没有自适应的 flattenColumns.forEach((column) => { // 根据 width、minWidth、80 的顺序设置高度 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) { // 计算固定列的宽度 let fixedWidth = 0; fixedColumns.forEach(function(column) { fixedWidth += column.realWidth; }); this.fixedWidth = fixedWidth; }// 计算右侧固定咧的宽度 const rightFixedColumns = this.store.states.rightFixedColumns; if (rightFixedColumns.length > 0) { let rightFixedWidth = 0; rightFixedColumns.forEach(function(column) { rightFixedWidth += column.realWidth; }); this.rightFixedWidth = rightFixedWidth; } } }export default TableLayout;

    推荐阅读