VariableSizeList不固定尺寸的列表
固定列思维:新增一个容器,采用 absolute绝对定位的方法渲染
<VariableSizeListitemSize={index => index}/>
VirtualTable
import React, {memo, useState} from 'react';import PropTypes from 'prop-types';import {VariableSizeList as List} from 'react-window';import AutoSizer from 'react-virtualized-auto-sizer';import {Icon} from 'antd';import classNames from 'classnames';VirtualTable.propTypes = {dataSource: PropTypes.array.isRequired,onChange: PropTypes.func.isRequired,};function VirtualTable({dataSource, onChange}) {const [sortIcon, setSortIcon] = useState('caret-up');const children = childrenColumns([{label: '综合', value: 0}, {label: '评价', value: 1}]);const {length} = dataSource// 数组第一个 values遍历生成表头const {values} = dataSource[0] || {};const columns = getColumns({values, children});if (dataSource.length) {columns.unshift(...mapColumns(['学科', '成绩']));}function onSort({index, colIndex}) {setSortIcon(prev => {const icon = prev === 'caret-up' ? 'caret-down' : 'caret-up';dataSource.sort((a, b) => {const current = a.values[colIndex-2][index]const next = b.values[colIndex-2][index]return (icon === 'caret-up') ? next - current : current - next;})return icon;});}function RenderThead({item, index}) {if (!item.children) {const style = {height: 81, lineHeight: '80px', padding: 8}return (<div className='tr' style={style}>{item.name}</div>)}function onClick({e, ...value}) {onSort(value)e.currentTarget.classList.add('on')}return (<div className='tr'><div className='tr-first'>{String(item?.name).substr(0, 5)}</div><div className="flex">{item.children.map((child, i) => {if (!child.name) return nullreturn (<div className='th flex-1' key={`${index}-${i}-thead`}>{child.name}<Icontype={sortIcon}className='sort-icon'onClick={(e) => onClick({e, index: i, child, colIndex: index})}/></div>)})}</div></div>)}function RenderTbody({index}) {return dataSource.map((item, i) => {const {keys, values} = item;const {length = 0} = keys;const oddClass = classNames({tr: true,flex: true,odd: i % 2 === 0});if(index < length) {return (<div className={oddClass}><div className='flex-1'>{keys[index]}</div></div>)}const colItem = values[index - length]if (!colItem) return null;const [time, ...args] = colItem;return (<div className={oddClass}>{args.map((item, i) => {return (<divkey={`${index}-${i}`}className='flex-1'onClick={() => onChange({index: i, time})}>{item === null ? '-' : item}</div>)})}</div>);})}function Column(value) {const {index, style} = value;const item = columns[index];if (!item || index < 2) return null;return (<div style={style}><RenderThead index={index} item={item}/><RenderTbody index={index}/></div>)}return (<AutoSizer>{({width, height}) => {console.log('wh', width, height)return (<><div className="_list flex lock" style={{height: (length + 2) * 41}}><div style={{flex: 1}}><RenderThead index={0} item={columns[0]}/><RenderTbody index={0}/></div><div style={{flex: 1}}><RenderThead index={1} item={columns[1]}/><RenderTbody index={1}/></div></div><ListclassName='_list'width={width}height={(length + 2) * 41 + 15}itemCount={columns.length}itemSize={index => (index < 2) ? 90 : 160}layout="horizontal">{Column}</List></>);}}</AutoSizer>);}export default memo(VirtualTable);// 固定左侧表头function mapColumns(dataSource) {return dataSource?.map((key, index) => ({name: key,key: 'keys',index,})) || [];}// children 表头function childrenColumns(dataSource) {return dataSource.map(({label}, index) => ({name: label,index,}));}// 数组第一个 values遍历生成表头function getColumns({values, children}) {return values.map(({time}, index) => {return {name: time,children,index,};});}
