我使用react-virtualized Table渲染一个包含很多行的表。我不希望由于固定的列宽而修剪长文本,因此我想使用CellMeasurer动态测量宽度。
这是使用网格的示例。很好。
render() {
const {width} = this.props;
return (
<Grid
className={styles.BodyGrid}
columnCount={1000}
columnWidth={this._cache.columnWidth}
deferredMeasurementCache={this._cache}
height={400}
overscanColumnCount={0}
overscanRowCount={2}
cellRenderer={this._cellRenderer}
rowCount={50}
rowHeight={35}
width={width}
/>
);
}
但是Table
和Column
都没有deferredMeasurementCache
道具。我当前的代码如下:
return (
<div>
<AutoSizer disableHeight>
{({width}) => (
<Table
ref="Table"
disableHeader={disableHeader}
headerClassName={styles.headerColumn}
headerHeight={headerHeight}
height={height}
noRowsRenderer={this._noRowsRenderer}
overscanRowCount={overscanRowCount}
rowClassName={this._rowClassName}
rowHeight={useDynamicRowHeight ? this._getRowHeight : rowHeight}
rowGetter={rowGetter}
rowCount={rowCount}
scrollToIndex={scrollToIndex}
sort={this._sort}
sortBy={sortBy}
sortDirection={sortDirection}
width={width}>
<Column
label="Index"
cellDataGetter={({rowData}) => rowData.index}
dataKey="index"
disableSort={!this._isSortEnabled()}
width={60}
/>
<Column .../>
</Table>
)}
</Autosizer>
</div>
);
如何在表格中使用Measurer
?
答案 0 :(得分:2)
已记录的用于React-virtualized的API不支持在CellMeasurer
中使用Table
。剩下的一些选项可以在react-virtualized中使用,包括:
Grid
和外部列标题实现Table
来实现,并且依赖于API中未记录的内部结构以下概述了后一种方法的解决方案,该方法可与react-virtualized v9.21.1(截至2019年7月的最新版本)一起使用。当然,这种方法可能会在将来的版本中发生变化,从而改变某些东西。
有几个问题要处理,包括:
Table
在内部使用Grid
来提供虚拟化的滚动,但是并没有在需要的地方暴露在API中。Grid
只有一列,它包含一行中所有Column
个单元格,但是Grid
作为父级传递来呈现Column
单元格。结果,一个Grid
单元可以与许多Column
单元相关联,Grid
和CellMeasurer
不支持这种情况。CellMeasurer
中使用Grid
取决于Grid
直接管理一行中的所有单元,而没有中间的rowRenderer
,而Table
有自己的行渲染逻辑。 [在下面的代码示例中,某些数据元素和函数与模块级声明一起显示。实际上,可以将它们定义为包含Table
的组件的成员,或者在某些情况下,可以将它们作为props传递给包含Table
的组件。]
以下解决方案通常可以解决这些问题:
在这种情况下,将使用两个CellMeasurerCache实例。 cellCache
用于单个Column
单元格的高度。 rowCache
用于行的高度。
const cellCache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 20, // keep this <= any actual row height
minHeight: 10, // keep this <= any actual row height
});
const rowCache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 37, // tune as estimate for unmeasured rows
minHeight: 10, // keep this <= any actual row height
});
对于Table
组件:
rowCache
添加为deferredMeasurementCache
道具rowRenderer
函数rowHeight
函数 <Table
...
deferredMeasurementCache={rowCache}
rowRenderer={rowRenderer}
rowHeight={rowHeight}
>
稍后将显示功能。 Table
对deferredMeasurementCache
不会做任何事情,只是将它作为道具传递给Table
的{{1}}。
对于每个需要测量的Grid
,添加一个Column
函数。在许多更简单的情况下,可以对所有测量列使用相同的功能:
cellRenderer
为帮助协调两个缓存的使用,需要三个附加数据项:
<Column
...
cellRenderer={measuredCellRenderer}
/>
const aMeasuredColumnIndex = 2; // any measured column index will do
let rowParent = null; // let a cellRenderer supply a usable value
const cellParent = { // an intermediary between measured row cells
// and their true containing Grid
invalidateCellSizeAfterRender: ({rowIndex}) => {
if (rowParent &&
typeof rowParent.invalidateCellSizeAfterRender == 'function') {
rowParent.invalidateCellSizeAfterRender({columnIndex: 0, rowIndex});
}
},
}
用于将表的网格暴露给rowRenderer。 rowParent
充当两个缓存之间,一行,其cellParent
单元和Column
的{{1}}之间的中介。
接下来是前面提到的三个功能:
Table
请注意,Grid
有两种不同用法。一个在function measuredCellRenderer({rowIndex, columnIndex, parent, cellData}) {
rowParent = parent; // parent is the Table's grid,
// save it for use by rowRenderer
return (
<CellMeasurer
cache={cellCache}
columnIndex={columnIndex}
parent={cellParent}
rowIndex={rowIndex}
>
<div>{cellData}</div>
</CellMeasurer>
);
// Note: cellData is wrapped in a <div> to facilitate height
// styling, for example adding padding to the <div>, because CellMeasurer
// measures the height of the content box.
}
function rowRenderer(params) {
return (
<CellMeasurer
cache={rowCache}
columnIndex={0}
key={params.key}
parent={rowParent}
rowIndex={params.rowIndex}
>
{Table.defaultProps.rowRenderer(params)}
</CellMeasurer>
);
}
function rowHeight({index}) {
let cellCacheRowHeight = cellCache.rowHeight({index});
if (cellCache.has(index, aMeasuredColumnIndex)) {
rowCache.set(index, 0, 20, cellCacheRowHeight);
// the 20 above is a somewhat arbitrary number for width,
// which is not relevant
}
return cellCacheRowHeight;
}
函数内部,并使用CellMeasurer
和measuredCellRenderer
。另一个在cellCache
函数内部,并使用cellParent
和rowRenderer
。
此外,rowCache
函数不仅报告行的高度。它还负责将rowParent
中行的rowHeight
转移到rowHeight
中第一列也是唯一列的行单元格高度。
当表中只有一个测量列时,可以稍微简化此解决方案。只需要一个cellCache
。单个缓存可以满足
rowCache
和CellMeasurerCache
的角色。结果:
cellCache
;可以将其删除。对rowCache
的引用可以由对cellParent
的引用替换,或者在使用cellParent
函数的情况下,可以将rowParent
measuredCellRenderer
道具直接设置为CellMeasurer
函数参数。parent
内,parent
必须为measuredCellRenderer
进行硬编码,即使所测量的列不是表中的第一列。CellMeasurer
函数中的columnIndex={0}
语句。if
可以被删除,因为它仅在rowHeight
aMeasuredColumnIndex
语句中被引用。