Grid是一个窗口网格。Grid网格只根据当前的水平/垂直滚动位置渲染填充自身所需的单元格。react
Props浏览器
属性 | 类型 | 必选? | 描述 |
---|---|---|---|
autoContainerWidth | Boolean | 否 | 将内部可滚动的容器宽度设为自动。 |
autoHeight | Boolean | 否 | Grid外部的高度设置为自动。这个属性只能和WindowScroller高阶组件结合使用 |
autoWidth | Boolean | 否 | Grid外部的宽度设置为自动。这个属性只能和WindowScroller高阶组件结合使用 |
cellRangeRenderer | Function | 否 | 负责渲染一组给定索引范围的单元格 |
cellRenderer | Function | 是 | 负责渲染给定行列索引的单元格 |
className | String | 否 | 可选的自定义CSS类名,附加到根Grid元素上 |
columnCount | Number | 是 | 网格列的数量 |
columnWidth | Number or Function | 是 | 一个固定的列宽(数字)或一个函数返回给定索引(({index: number}): number)的列宽。若使用函数,能够指定estimatedColumnSize来优化滚动行为。 |
containerProps | Object | 否 | 负责添加属性到cell-container(例如onWheel事件) |
containerRole | String | 否 | cell-ContainerARIA角色,默认是rowgroup |
containerStyle | Object | 否 | 可选的自定义行内样式附加内部的cell-container元素 |
deferredMeasurementCache | CellMeausrer | 否 | 若CellMeasure用于计算Grid的子元素,该属性必须是CellMeausrerCache的指针。一个共享的CellMeasurerCache引用使Grid和CellMeasurer共享计算数据 |
estimatedColumnSize | Number | 否 | 用于在全部列被计算以前预估整个Grid的宽度。被预估的整宽会在列渲染后调整 |
estimatedRowSize | Number | 否 | 用于在全部行被计算以前预估整个Grid的高度。被预估的整高会在行渲染后调整 |
height | Number | 是 | Grid的高度;该属性决定了可见的行数量 |
id | String | 否 | 可选的自定义ID来附加到根Grid元素 |
isScrolling | Boolean | 否 | 重写内部是否处于滚动的状态,整个属性主要服务于WindowScroller组件 |
isScrollingOptOut | Boolean | 否 | 防止在滚动端从新渲染可见单元格 |
onContentRenderer | Function | 否 | 使用刚渲染的Grid区域的信息调用回调函数,旨在可见行发生改变时调用:({columnOverscanStartIndex: number, columnOverscanStopIndex: number, columnStartIndex: number, columnStopIndex: number, rowOverscanStartIndex: number, rowOverscanStopIndex: number, rowStartIndex: number, rowStopIndex: number}): void |
onScroll | Function | 否 | 每当内部可滚动区域内的滚动偏移发生变化时,将调用回调:({ clientHeight: number, clientWidth: number, scrollHeight: number, scrollLeft: number, scrollTop: number, scrollWidth: number }): void |
onScrollbarPresenceChange | Function | 否 | 每当添加或移除水平或垂直滚动条时调用:({ horizontal: boolean, size: number, vertical: boolean }): void |
overscanColumnCount | Number | 否 | 渲染可见的网格切片先后的列数量。能够减小在某些浏览器或设备滚动期间的闪烁。 |
overscanIndicesGetter | Function | 否 | 负责计算在指定范围以前和以后要扫描的单元格数量 |
overscanRowCount | Number | 否 | 渲染可见的网格切片先后的行数量。能够减小在某些浏览器或设备滚动期间的闪烁。 |
role | String | 否 | 可选的重写默认ARIA,默认是grid |
rowCount | Number | 是 | 网格中行的数量 |
rowHeight | Number or Function | 是 | 固定的行高(数字)或一个函数返回给定索引的行高:({index: nmber}): number。若是使用函数,指定estimatedRowSize来优化滚动行为 |
scrollingResetTimeInterval | Number | 否 | 在上一次滚动事件以后等待此时间,而后重置网格指针事件;默认为150ms。 |
scrollLeft | Number | 否 | 水平偏移量 |
scrollToAlignment | String | 否 | 控制scrolled-to-cells的对齐方式。默认(自动)滚动到可能的最小数量确保指定单元格彻底可见。使用start将指定单元格对其到网格左上,使用end对齐到右下。使用center将指定单元格对其到容器中间。 |
scrollToColumn | Number | 否 | 确保可见的列索引(必要时强行滚动),优先于scrollLeft |
scrollToRow | Number | 否 | 确保可见的行索引。优先于scrollTop |
scrollTop | Number | 否 | 垂直偏移量 |
style | Object | 否 | 可选的自定义内联样式,附加到根Grid元素 |
tabIndex | Number | 否 | 可选的重写默认的标签索引。默认是0 |
width | Nubmer | 是 | Grid的宽度,这个属性决定了可见的列的数量 |
公共方法缓存
获取给定单元格的偏移量和对齐方式。安全
获取预估的整行高度。app
获取预估的整列宽度dom
此方法处理源于外部滚动控件的滚动事件。这是一种高级方法,除非您要实现自定义滚动条解决方案,不然可能不该该使用它。ide
预计算全部Grid中的行和列。函数
在指定索引后(默认是0)从新计算行高和列宽。布局
若是动态列或行的大小改变,但没有其余更改,则应调用此函数。由于Grid只接受columnCount和rowCount,它没法检测基础数据什么时候更改。性能
此方法还将强制执行渲染周期(经过forceUpdate),以确保更新的测量值反映在渲染的网格中。
确保行和列可见。这个方法可被用来当用户滚动远离某个单元格以后,安全地滚回到原处。即便已经滚动到了改位置。
滚动指定偏移量。用于设置位置变化的动画。
类名
Grid组件支持下列静态类名:
属性 | 描述 |
---|---|
ReactVirtualized__Grid | (外部)主要元素 |
ReactVirtualizedGridinnerScrollContainer | 内部滚动区域 |
cellRangeRenderer
这是一个高级属性。当网格须要其余覆盖的UI(例如甘特图或日历应用程序)的状况下,它颇有用。使用onScroll回调或ScrollSync 高阶组件能够更轻松地解决许多用例。
若是你想重写cellRangeRenderer,最简单的方法是加强默认的实现:
import {defaultCellRangeRenderer, Grid} from 'react-virtualized';function cellRangeRenderer(props) { const children = defaultCellRangeRenderer(props); children.push(<div>My custom overlay</div>); return children; }function CustomizedGrid(props) { return <Grid cellRangeRenderer={cellRangeRenderer} {...props} />; }复制代码
若是须要更大的自定义,则可能须要派生defaultCellRangeRenderer函数。
该函数接受如下命名参数:
function cellRangeRenderer({ cellCache, // Temporary cell cache used while scrolling cellRenderer, // Cell renderer prop supplied to Grid columnSizeAndPositionManager, // @see CellSizeAndPositionManager, columnStartIndex, // Index of first column (inclusive) to render columnStopIndex, // Index of last column (inclusive) to render horizontalOffsetAdjustment, // Horizontal pixel offset (required for scaling) isScrolling, // The Grid is currently being scrolled rowSizeAndPositionManager, // @see CellSizeAndPositionManager, rowStartIndex, // Index of first row (inclusive) to render rowStopIndex, // Index of last row (inclusive) to render scrollLeft, // Current horizontal scroll offset of Grid scrollTop, // Current vertical scroll offset of Grid styleCache, // Temporary style (size & position) cache used while scrolling verticalOffsetAdjustment, // Vertical pixel offset (required for scaling) }) { const renderedCells = []; for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {// This contains :offset (top) and :size (height) information for the celllet rowDatum = rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex);for ( let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++ ) { // This contains :offset (left) and :size (width) information for the cell let columnDatum = columnSizeAndPositionManager.getSizeAndPositionOfCell( columnIndex, ); // Be sure to adjust cell position in case the total set of cells is too large to be supported by the browser natively. // In this case, Grid will shift cells as a user scrolls to increase cell density. let left = columnDatum.offset + horizontalOffsetAdjustment; let top = rowDatum.offset + verticalOffsetAdjustment; // The rest of the information you need to render the cell are contained in the data. // Be sure to provide unique :key attributes. let key = `${rowIndex}-${columnIndex}`; let height = rowDatum.size; let width = columnDatum.size; // Now render your cell and additional UI as you see fit. // Add all rendered children to the :renderedCells Array.} } return renderedCells; }复制代码
overscanIndicesGetter
这是一个高级属性。这个函数负责计算指定范围先后扫描的单元格数量。默认下react-virtualized根据滚动方向优化了扫描的单元数。若是你想自定义这个行为,能够forkdefaultOverscanIndicesGetter函数。
function overscanIndicesGetter ({ direction, // One of "horizontal" or "vertical" cellCount, // Number of rows or columns in the current axis scrollDirection, // 1 (forwards) or -1 (backwards) overscanCellsCount, // Maximum number of cells to over-render in either direction startIndex, // Begin of range of visible cells stopIndex // End of range of visible cells }) { return {overscanStartIndex: Math.max(0, startIndex - overscanCellsCount),overscanStopIndex: Math.min(cellCount - 1, stopIndex + overscanCellsCount) } }复制代码
cellRender
负责渲染单个单元格,给出了行列的索引。此函数接受下列命名参数:
function cellRenderer({ columnIndex, // Horizontal (column) index of cell isScrolling, // The Grid is currently being scrolled isVisible, // This cell is visible within the grid (eg it is not an overscanned cell) key, // Unique key within array of cells parent, // Reference to the parent Grid (instance) rowIndex, // Vertical (row) index of cell style, // Style object to be applied to cell (to position it); // This must be passed through to the rendered cell element. }) { // Grid data is a 2d array in this example... const user = list[rowIndex][columnIndex]; // If cell content is complex, consider rendering a lighter-weight placeholder while scrolling. const content = isScrolling ? '...' : <User user={user} />; // Style is required since it specifies how the cell is to be sized and positioned. // React Virtualized depends on this sizing/positioning for proper scrolling behavior. // By default, the grid component provides the following style properties: // position // left // top // height // width // You can add additional class names or style properties as you would like. // Key is also required by React to more efficiently manage the array of cells. return (<div key={key} style={style}> {content}</div> ); }复制代码
基础的Grid示例
下面是一个很是基础的Grid示例。这个网格展现了一组队具备固定行列大小的对象。(也支持动态的)。
import React from 'react';import ReactDOM from 'react-dom';import {Grid} from 'react-virtualized';// Grid data as an array of arraysconst list = [ ['Brian Vaughn', 'Software Engineer', 'San Jose', 'CA', 95125 /* ... */], // And so on...];function cellRenderer({columnIndex, key, rowIndex, style}) { return (<div key={key} style={style}> {list[rowIndex][columnIndex]}</div> ); }// Render your gridReactDOM.render( <GridcellRenderer={cellRenderer}columnCount={list[0].length}columnWidth={100}height={300}rowCount={list.length}rowHeight={30}width={300} />, document.getElementById('example'), );复制代码
CellMeasurer是经过一种用户不可见的渲染方式自动计算单元格内容的高阶组件。能够指定一个固定的宽度来计算动态的高度(反之亦然)。这是一个高级的组件,但具备一些局限性和性能方面的注意事项。
CellMeasurer能够和Grid,List和Table这些组件一块儿使用,但不能够和Collection一块儿使用。
Props
属性 | 类型 | 必选? | 描述 |
---|---|---|---|
cache | CellMeasurerCache | 是 | 在CellMeasure和他们的父级Grid之间共享的缓存 |
children | Element or Function | 是 | 能够是一个React元素(例如<div />)或者一个函数 (例如({measure, registerChild}) => <div ref={registerChild} />) |
columnIndex | number | 是 | 经计算的列index(在父级Grid里)或者0(使用List或Table) |
parent | Grid | 是 | 父级Grid的引用;改值是由Grid传递给cellRenderer,应该原样传递 |
rowIndex | number | 是 | 经计算的行index(在父级Grid里) |
Render Props
属性 | 类型 | 描述 |
---|---|---|
measure | Function | 执行单元格计算 |
registerChild | Function | 指定要计算的Dom元素,能够被用做为ref(默认是WindowScroller使用ReactDOM.findDOMNode函数) |
CellMeasurerCache
CellMeasurerCache存储了CellMeasurer的计算而且将他们共享与一个父级Grid。应当基于你所须要的计算类型来配置。接受如下参数:
属性 | 类型 | 必选? | 描述 |
---|---|---|---|
defaultHeight | number | 否 | 未计算的单元格将改值初始化高度 |
defaultWidth | number | 否 | 未计算的单元格将改值初始化宽度 |
fixedHeight | number | 否 | 渲染单元格将拥有一个固定的高度,动态的宽度 |
fixedWidth | number | 否 | 渲染单元格将拥有一个固定的宽度,动态的高度 |
minHeight | number | 否 | 多个单元格的派生行高度不该该小于改值 |
minWidth | number | 否 | 多个单元格的派生列宽度不该该小于改值 |
keyMapper | number | 否 | 能够更智能地将给定的列和行索引映射到项目ID。这样能够防止在修改其父级时单元格缓存失效。(rowIndex: number, columnIndex: number) => any |
注意上述全部属性都是可选的,你必须至少提供其中一些。CellMeasureerCache并不意味着同时计算动态地宽度和高度。当行(或列)的大小等于这个行最大单元格的大小时这样作会十分低效。
CellMeasurerCache通用的方法
重置一个指定单元格的计算缓存
应当在单元格须要从新计算来处理动态地内容时调用。(例如用加载的内容替换加载图标或对有状态单元的状态变化作出响应)
重置全部单元格的计算缓存
应当在Grid,List,Table组件因使用响应式布局触发resize事件须要回流内容的时候调用。(例如修改窗口大小时须要一个单元格高度的响应)
例子
这个例子展现了固定行高动态列宽的Grid。
import React from 'react';import { CellMeasurer, CellMeasurerCache, Grid } from 'react-virtualized';// In this example, average cell width is assumed to be about 100px.// This value will be used for the initial `Grid` layout.// Cell measurements smaller than 75px should also be rounded up.// Height is not dynamic.const cache = new CellMeasurerCache({ defaultWidth: 100, minWidth: 75, fixedHeight: true});function cellRenderer ({ columnIndex, key, parent, rowIndex, style }) { const content // Derive this from your data somehow return (<CellMeasurer cache={cache} columnIndex={columnIndex} key={key} parent={parent} rowIndex={rowIndex}> <divstyle={{ ...style, height: 35, whiteSpace: 'nowrap' }} >{content} </div></CellMeasurer> ); }function renderGrid (props) { return (<Grid {...props} columnWidth={cache.columnWidth} deferredMeasurementCache={cache} cellRenderer={cellRenderer}/> ); }复制代码
CellMeasurer默认使用findDOMNode来获取到DOM元素去计算。但这个API在React严格模式下是不推荐的。因此你可能想要避免这个用法。做为代替,你可使用registerChild属性来指定元素。(例如将他做为一个ref传入)
import React from 'react';import { CellMeasurer, CellMeasurerCache, Grid } from 'react-virtualized';// In this example, average cell width is assumed to be about 100px.// This value will be used for the initial `Grid` layout.// Cell measurements smaller than 75px should also be rounded up.// Height is not dynamic.const cache = new CellMeasurerCache({ defaultWidth: 100, minWidth: 75, fixedHeight: true});function cellRenderer ({ columnIndex, key, parent, rowIndex, style }) { const content // Derive this from your data somehow return (<CellMeasurer cache={cache} columnIndex={columnIndex} key={key} parent={parent} rowIndex={rowIndex}> {({registerChild}) => (<div style={{...style,height: 35,whiteSpace: 'nowrap' }} > {content}</div> )}</CellMeasurer> ); }function renderGrid (props) { return (<Grid {...props} columnWidth={cache.columnWidth} deferredMeasurementCache={cache} cellRenderer={cellRenderer}/> ); }复制代码
本示例说明如何将CellMeasurer组件与List组件一块儿使用,以显示动态高度行。与上述实例不一样在于:行高是由图片数据加载完成后决定的。为此将一个函数传入CellMeasurer组件,接受measure和registerChild两个参数。measure应在单元格内容计算完后调用。(本例中为图片数据加载完成后)
import React from 'react';import { CellMeasurer, CellMeasurerCache, List } from 'react-virtualized';// In this example, average cell height is assumed to be about 50px.// This value will be used for the initial `Grid` layout.// Width is not dynamic.const cache = new CellMeasurerCache({ defaultHeight: 50, fixedWidth: true});function rowRenderer ({ index, isScrolling, key, parent, style }) { const source // This comes from your list data return (<CellMeasurer cache={cache} columnIndex={0} key={key} parent={parent} rowIndex={index}> {({ measure, registerChild }) => ( // 'style' attribute required to position cell (within parent List)<div ref={registerChild} style={style}> <imgonLoad={measure}src={source} /></div> )}</CellMeasurer> ); }function renderList (props) { return (<List {...props} deferredMeasurementCache={cache} rowHeight={cache.rowHeight} rowRenderer={rowRenderer}/> ); }复制代码
// Normally, every cell gets measured individually and is very slow.// However, with the keyMapper prop we can specify a constant return value and// tell CellMeasurer that all measurements after the first one will hit the// cache and we get a speedy solution.const cache = new CellMeasurerCache({ defaultHeight: 30, fixedWidth: true, keyMapper: () => 1, });复制代码
局限性和性能事项
计算列宽须要计算全部行来决定该列发生的最大宽度。计算行高亦如此。所以当列和单元格同时包含庞大的数据时,使用这个Grid的高阶组件并非一个好的主意。
因为该组件一次只计算一个单元格的宽高,因此若是用户用滚动条或者scoll-to-cell属性一次性跳过许多行(或列)时将会卡慢。不幸的是如今没有针对该性能局限性的解决方案。