react-window 固定行 sticky
import React, { createContext, forwardRef } from "react";
import { FixedSizeList as List } from "react-window";
const Context = createContext();
const ItemWrapper = ({ data, index, style }) => {
const { ItemRenderer, stickyIndices } = data;
// 过滤掉固定的行
if (stickyIndices && stickyIndices.includes(index)) {
return null;
}
return <ItemRenderer index={index} style={style} />;
};
// 滚动的行
const Row = ({ index, style }) => {
return (
<div className="row" style={style}>
Row {index}
</div>
)
};
// 固定的行
const StickyRow = ({ index, style }) => (
<div className="sticky" style={style}>
Sticky Row {index}
</div>
);
const innerElementType = forwardRef(({ children, ...rest }, ref) => {
return (
<Context.Consumer>
{({ stickyIndices }) => (
<div ref={ref} {...rest}>
{stickyIndices.map(index => (
<StickyRow
index={index}
key={index}
style={{ top: index * 35, left: 0, width: "100%", height: 35 }}
/>
))}
{children}
</div>
)}
</Context.Consumer>
)
});
function StickyList(props) {
const { children, stickyIndices, ...rest } = props;
return (
<Context.Provider value={{ ItemRenderer: children, stickyIndices }}>
<List itemData={{ ItemRenderer: children, stickyIndices }} {...rest}>
{ItemWrapper}
</List>
</Context.Provider>
);
}
function App() {
return (
<StickyList
height={150}
innerElementType={innerElementType}
itemCount={1000}
itemSize={35}
stickyIndices={[0, 1]} // 那几列固定
width={300}
>
{Row}
</StickyList>
)
}
export default App;
less
.sticky {
position: sticky !important;
position: -webkit-sticky !important;
z-index: 2;
}
.row, .sticky {
display: flex;
align-items: center;
background-color: white;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}