
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