react-composable-list
Version:
104 lines (89 loc) • 2.81 kB
JSX
import React from 'react/addons';
class ListInner extends React.Component {
_renderChildren() {
let children = this.props.items;
let scrollTop = this.props.scrollTop;
let outerHeight = this.props.height;
let topHiddenHeight = 0,
bottomHiddenHeight = 0,
visibleHeight = 0,
firstRenderIndex = -1,
lastRenderIndex = Infinity;
let realChildren = [];
for (let i = 0; i < children.length; i++) {
let childHeight = children[i].props.height;
if (visibleHeight >= outerHeight) {
if (lastRenderIndex === Infinity) {
lastRenderIndex = i - 1;
}
bottomHiddenHeight += childHeight;
}
else if (topHiddenHeight + childHeight > scrollTop) {
if (firstRenderIndex === -1) {
firstRenderIndex = i;
visibleHeight += topHiddenHeight - scrollTop;
}
realChildren.push(children[i]);
visibleHeight += childHeight;
}
else {
topHiddenHeight += childHeight;
}
}
if (visibleHeight < outerHeight) {
for (let i = firstRenderIndex - 1; i >= 0; i--) {
if (visibleHeight < outerHeight) {
realChildren.unshift(children[i]);
let height = children[i].props.height;
visibleHeight += height;
topHiddenHeight -= height;
firstRenderIndex -= 1;
} else {
break;
}
}
}
// 前后 预先渲染好 各20个
let prepareNodeCount = 20;
for (let i = firstRenderIndex - 1;
i >= 0 && i >= firstRenderIndex - prepareNodeCount;
i--)
{
realChildren.unshift(children[i]);
let height = children[i].props.height;
visibleHeight += height;
topHiddenHeight -= height;
}
for (let i = lastRenderIndex + 1;
i < children.length && i <= lastRenderIndex + prepareNodeCount;
i++)
{
realChildren.push(children[i]);
let height = children[i].props.height;
visibleHeight += height;
bottomHiddenHeight -= height;
}
realChildren.push(<div key="bottom_H" style={{height: `${bottomHiddenHeight}px`}}></div>);
realChildren.unshift(<div key="top_H" style={{height: `${topHiddenHeight}px`}}></div>);
return realChildren;
}
render() {
return (
<div className="mzl-list-container">
{ this._renderChildren() }
</div>
);
}
}
ListInner.propTypes = {
width: React.PropTypes.number.isRequired,
height: React.PropTypes.number.isRequired,
scrollTop: React.PropTypes.number.isRequired,
items: React.PropTypes.array.isRequired
};
ListInner.defaultProps = {
scrollTop: 0,
items: []
};
ListInner.prototype.shouldComponentUpdate = React.addons.PureRenderMixin.shouldComponentUpdate;
export default ListInner;