
react-window 固定列参考
https://codesandbox.io/s/0mk3qwpl4l?file=/src/index.js:0-1735
antd Table3x https://github.com/ctq123/ant-virtual-table
antd Table4x https://ant.design/components/table/#components-table-demo-virtual-list
https://github.com/wubostc/virtualized-table-for-antd
缺点:
- 点击排序会自动刷新表格
- innerElementType就是 sticky的列;固定列要和滚动的列分开 ```jsx import React, {memo, useState, createContext, forwardRef} 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’;
const Context = createContext();
VirtualTable.propTypes = { dataSource: PropTypes.array.isRequired, };
function VirtualTable({dataSource}) { 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, onClick}); if (dataSource.length) { columns.unshift(…mapColumns([‘学科’, ‘成绩’])); }
function onClick(value) { console.log(‘click’, value) }
function onSort({index, colIndex}) { setSortIcon(prev => { return prev === ‘caret-up’ ? ‘caret-down’ : ‘caret-up’; });
setTimeout(() => {dataSource.sort((a, b) => {const item = a.values[colIndex][index]const bitem = b.values[colIndex][index]return (sortIcon === 'caret-up') ? bitem - item : item - bitem;})}, 0)
}
function RenderThead({item, index}) { if (!item.children) { const style = {height: 81, lineHeight: ‘80px’, padding: 8} return (
function onClick({e, ...value}) {onSort(value)e.currentTarget.classList.add('on')}return (<div className='tr'><div className='tr-first'>{item.name}</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 (<div className={oddClass}><div className='flex-1' /></div>);const [time, a, b, c, ...args] = colItem;return (<div className={oddClass}>{args.map((item, i) => {return (<divkey={`${index}-${i}`}className='flex-1'onClick={() => onClick({index: i, time})}>{item === null ? '' : item}</div>)})}</div>);})
}
function Column(value) { const {index, style} = value; const item = columns[index]; if (!item) return null;
return (<div style={style}><RenderThead index={index} item={item}/><RenderTbody index={index}/></div>)
}
const ItemWrapper = ({data, index, style}) => {
const {ItemRenderer, stickyIndices} = data;
// 过滤掉固定的行
if (stickyIndices && stickyIndices.includes(index)) {
return null;
}
return
function StickyList(props) {
const {children, stickyIndices, …rest} = props;
return (
{ItemWrapper}
// 固定的行 const StickyRow = ({index}) => { console.log(12, index) const item = columns[index]; if (!item) return null;
const _style = {height: 81, lineHeight: '80px', padding: 8}return (<div style={{float: 'left', width: '50%'}}><div className='tr' style={_style}>{item.name}</div><RenderTbody index={index}/></div>)
};
const innerElementType = forwardRef(({children, …rest}, ref) => {
return (
return (
export default memo(VirtualTable);
// 固定左侧表头 function mapColumns(dataSource) { return dataSource.map((key, i) => ({ name: key, key: ‘keys’, })); }
// children 表头 function childrenColumns(dataSource) { return dataSource.map(({label}, i) => ({ name: label, index: i, key: ‘values’, })); }
// 遍历数组第一个values生成表头 function getColumns({values, children}) { return values.map(([time], i) => { return { name: toHours(time), children, }; }); }
RenderCell```jsxfunction RenderCell({ className, value = '' }) {return (<div className={className}><div className='flex-1'>{value}</div></div>);}
数据格式
[{keys: ['标题', '描述'],values: [{time: 1628148180000, title: '', desc: '', value: 100}]},{keys: ['标题', '描述'],values: [{time: 1628148190000, title: '', desc: '', value: 100}]},]
