
5 changed files with 864 additions and 209 deletions
@ -0,0 +1,228 @@ |
|||||
|
import ResizeObserver from 'resize-observer-polyfill'; |
||||
|
import { |
||||
|
debounce |
||||
|
} from 'lodash-es'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
tableResizeObserver: null, |
||||
|
tableWidth: 0 |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 初始化表格宽度监听
|
||||
|
initTableResizeObserver(tableRef, containerRef) { |
||||
|
this.$nextTick(() => { |
||||
|
const container = containerRef ? this.$refs[containerRef] : this.$el; |
||||
|
if (!container) { |
||||
|
console.warn('Table container not found'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 先断开已有观察者
|
||||
|
this.destroyTableResizeObserver(); |
||||
|
|
||||
|
this.tableResizeObserver = new ResizeObserver( |
||||
|
debounce(entries => { |
||||
|
const entry = entries[0]; |
||||
|
const newWidth = entry.contentRect.width; |
||||
|
|
||||
|
if (Math.abs(newWidth - this.tableWidth) > 5) { |
||||
|
this.tableWidth = newWidth; |
||||
|
this.syncTableColumns(tableRef); |
||||
|
} |
||||
|
}, 100) |
||||
|
); |
||||
|
|
||||
|
try { |
||||
|
this.tableResizeObserver.observe(container); |
||||
|
} catch (err) { |
||||
|
console.error('Failed to observe table:', err); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 同步表头和表体列宽
|
||||
|
syncTableColumns(tableRef) { |
||||
|
// const table = this.$refs[tableRef];
|
||||
|
const table = this.$refs[tableRef].$refs.guiptable; |
||||
|
// console.log(table, 'table====--');
|
||||
|
if (!table) return; |
||||
|
let columns = table.columns; |
||||
|
// console.log(table,table['columns'],table.bodyWidth,'table.columns===');
|
||||
|
// 计算各列宽度(由具体组件实现)
|
||||
|
const columnWidths = this.calculateColumnWidths(); |
||||
|
if (!columnWidths) return; |
||||
|
// console.log(columnWidths, 'table.columns===');
|
||||
|
// 设置列宽并同步表头表体
|
||||
|
this.$nextTick(() => { |
||||
|
// 设置列定义中的宽度
|
||||
|
columns.forEach(column => { |
||||
|
// console.log(column.property,'columns====columns');
|
||||
|
if (columnWidths[column.property]) { |
||||
|
column.width = columnWidths[column.property]; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 同步DOM元素的宽度
|
||||
|
// const headerCols = table.$el.querySelectorAll('.el-table__header col');
|
||||
|
// const bodyCols = table.$el.querySelectorAll('.el-table__body col');
|
||||
|
|
||||
|
// columns.forEach((column, index) => {
|
||||
|
// if (columnWidths[column.property] && headerCols[index] && bodyCols[index]) {
|
||||
|
// const width = columnWidths[column.property];
|
||||
|
// headerCols[index].width = width;
|
||||
|
// headerCols[index].style.setProperty('width',`${width}px`, 'important');
|
||||
|
// // headerCols[index].style.width = `${width}px`;
|
||||
|
// bodyCols[index].width = width;
|
||||
|
// bodyCols[index].style.setProperty('width',`${width}px`, 'important');
|
||||
|
// // bodyCols[index].style.width = `${width}px`;
|
||||
|
// }
|
||||
|
// });
|
||||
|
|
||||
|
// 强制表格重新布局
|
||||
|
table.doLayout(); |
||||
|
// this.syncFixedColumns(table);
|
||||
|
this.$nextTick(() => { |
||||
|
// 3. 同步主表格
|
||||
|
this.syncColumns( |
||||
|
table.$el, |
||||
|
columnWidths, |
||||
|
table.columns |
||||
|
); |
||||
|
|
||||
|
// 4. 同步固定列
|
||||
|
const fixedLeft = table.$el.querySelector('.el-table__fixed'); |
||||
|
const fixedRight = table.$el.querySelector('.el-table__fixed-right'); |
||||
|
|
||||
|
if (fixedLeft) this.syncColumns(fixedLeft, columnWidths, table.columns); |
||||
|
if (fixedRight) this.syncColumns(fixedRight, columnWidths, table.columns); |
||||
|
|
||||
|
// 5. 强制布局更新(需要两次nextTick确保固定列更新)
|
||||
|
this.$nextTick(() => { |
||||
|
table.doLayout(); |
||||
|
setTimeout(() => table.doLayout(), 50); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
}, |
||||
|
syncColumns(container, columnWidths, columns) { |
||||
|
const headerCols = container.querySelectorAll('.el-table__header col, [class*=-header-wrapper] col'); |
||||
|
const bodyCols = container.querySelectorAll('.el-table__body col, [class*=-body-wrapper] col'); |
||||
|
|
||||
|
columns.forEach((column, index) => { |
||||
|
const width = columnWidths[column.property]; |
||||
|
if (width && headerCols[index] && bodyCols[index]) { |
||||
|
headerCols[index].width = width; |
||||
|
// headerCols[index].style.width = `${width}px`;
|
||||
|
headerCols[index].style.setProperty('width',`${width}px`, 'important'); |
||||
|
|
||||
|
bodyCols[index].width = width; |
||||
|
// bodyCols[index].style.width = `${width}px`;
|
||||
|
bodyCols[index].style.setProperty('width',`${width}px`, 'important'); |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
// syncTableColumns(tableRef) {
|
||||
|
// const table = this.$refs[tableRef].$refs.guiptable;
|
||||
|
// if (!table) return;
|
||||
|
|
||||
|
// // 计算各列宽度
|
||||
|
// const columnWidths = this.calculateColumnWidths();
|
||||
|
// if (!columnWidths) return;
|
||||
|
|
||||
|
// this.$nextTick(() => {
|
||||
|
// // 1. 设置列定义的宽度
|
||||
|
// table.columns.forEach(column => {
|
||||
|
// if (columnWidths[column.property]) {
|
||||
|
// column.width = columnWidths[column.property];
|
||||
|
// column.realWidth = columnWidths[column.property]; // 关键:设置realWidth
|
||||
|
// }
|
||||
|
// });
|
||||
|
|
||||
|
// // 2. 同步DOM元素的宽度
|
||||
|
// const headerCols = table.$el.querySelectorAll('.el-table__header col');
|
||||
|
// const bodyCols = table.$el.querySelectorAll('.el-table__body col');
|
||||
|
// const headerCells = table.$el.querySelectorAll('.el-table__header .cell');
|
||||
|
// // const bodyCells = table.$el.querySelectorAll('.el-table__body .cell');
|
||||
|
|
||||
|
// table.columns.forEach((column, index) => {
|
||||
|
// if (columnWidths[column.property]) {
|
||||
|
// const width = columnWidths[column.property];
|
||||
|
|
||||
|
// // 同步colgroup中的宽度
|
||||
|
// if (headerCols[index]) {
|
||||
|
// headerCols[index].width = width;
|
||||
|
// headerCols[index].style.width = `${width}px`;
|
||||
|
// }
|
||||
|
// if (bodyCols[index]) {
|
||||
|
// bodyCols[index].width = width;
|
||||
|
// bodyCols[index].style.width = `${width}px`;
|
||||
|
// }
|
||||
|
|
||||
|
// // 同步单元格的实际宽度
|
||||
|
// if (headerCells[index]) {
|
||||
|
// headerCells[index].style.width = `${width}px`;
|
||||
|
// }
|
||||
|
// // body单元格通常不需要强制设置宽度
|
||||
|
// }
|
||||
|
// });
|
||||
|
|
||||
|
// // 3. 强制更新布局
|
||||
|
// table.store.scheduleLayout();
|
||||
|
|
||||
|
// // 4. 处理固定列
|
||||
|
// this.syncFixedColumns(table);
|
||||
|
// });
|
||||
|
// },
|
||||
|
|
||||
|
// syncFixedColumns(table) {
|
||||
|
// // 处理左侧固定列
|
||||
|
// const fixedLeftWrapper = table.$el.querySelector('.el-table__fixed');
|
||||
|
// if (fixedLeftWrapper) {
|
||||
|
// const fixedLeftCols = fixedLeftWrapper.querySelectorAll('col');
|
||||
|
// const originalCols = table.$el.querySelectorAll('.el-table__header col');
|
||||
|
|
||||
|
// fixedLeftCols.forEach((col, index) => {
|
||||
|
// if (originalCols[index]) {
|
||||
|
// const width = originalCols[index].width;
|
||||
|
// col.width = width;
|
||||
|
// // col.style.width = `${width}px`;
|
||||
|
// col.style.setProperty('width',`${width}px`, 'important');
|
||||
|
|
||||
|
// }
|
||||
|
// });
|
||||
|
|
||||
|
// // 强制重绘固定列
|
||||
|
// fixedLeftWrapper.style.display = 'none';
|
||||
|
// this.$nextTick(() => {
|
||||
|
// fixedLeftWrapper.style.display = '';
|
||||
|
// });
|
||||
|
// }
|
||||
|
|
||||
|
// // 同样处理右侧固定列...
|
||||
|
// },
|
||||
|
|
||||
|
|
||||
|
// 销毁观察者
|
||||
|
destroyTableResizeObserver() { |
||||
|
if (this.tableResizeObserver) { |
||||
|
this.tableResizeObserver.disconnect(); |
||||
|
this.tableResizeObserver = null; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 需要组件自己实现的计算列宽方法
|
||||
|
calculateColumnWidths() { |
||||
|
throw new Error('Component must implement calculateColumnWidths method'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
beforeDestroy() { |
||||
|
this.destroyTableResizeObserver(); |
||||
|
} |
||||
|
}; |
Loading…
Reference in new issue