从头开始构建的 ReactJS 无限滚动在一段时间后停止工作



我正在尝试通过从头开始实现无限滚动来学习 React。

算法:

  1. arr是一个包含 1000 个div 的数组
  2. arr2是来自arr的 21 个div 的数组切片。arr2通过滚动更新。
  3. 只有arr2中的元素应该被渲染
  4. 控制台显示正在渲染的当前arr范围

包括jQuery。

它工作了一点。但在大约 34 个元素之后停止。为什么?

(包括片段。或者,这里是JSBin:http://jsbin.com/yonabiv/edit?html,js,console,output(

var arr = [];
for (var i = 0; i<1000; i++) {

arr.push(i);
}
class Element extends React.Component{
render() {

const styleObj = {height: 100, backgroundColor:"hotpink"};

return (<div style={styleObj}> {this.props.data} </div>);
}
}
class List extends React.Component{
constructor(props) {
super(props);

this.state = {
visibleStart: 0,
visibleEnd: 20
};

}
render() {
var arr2 = arr.slice(this.state.visibleStart, this.state.visibleEnd);
var renderedOutput = arr2.map((item,index) => <Element data={item} key={index} />)
return (
<div>
{renderedOutput}
</div>
);
}

componentDidMount() {
window.addEventListener('scroll', this.handleScroll.bind(this))
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll.bind(this))
}
handleScroll(event) {
var visibleStart = Math.floor($(window).scrollTop()/100);
var visibleEnd = visibleStart + 20;
console.log(visibleStart + " " + visibleEnd);
this.setState({
visibleStart: visibleStart,
visibleEnd: visibleEnd
});

}

}
ReactDOM.render(<List />, document.getElementById("app"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>React Infinite Scroll</title>
</head>
<body>
<div id="app"></div>

</body>
</html>

这是因为您已经到达了父级高度的末尾,您这样做是因为您只渲染了 20 个元素(每个元素为 100px(,这就是父级的高度。
您可以将下一组元素链接到渲染列表中(将其存储在状态中并添加更多元素?
我做了一个例子只是为了说明差异,当然这并不完美,可能有一些错误,但这只是为了让你理解它停止的原因。

var arr = [];
for (var i = 0; i<1000; i++) {

arr.push(i);
}
class Element extends React.Component{
render() {

const styleObj = {height: 100, backgroundColor:"hotpink"};

return (<div style={styleObj}> {this.props.data} </div>);
}
}
class List extends React.Component{
constructor(props) {
super(props);

this.state = {
visibleStart: 0,
visibleEnd: 20,
listItems: arr.slice(0, 20)
};

}
render() {
const {listItems} = this.state;
var renderedOutput = listItems.map((item,index) => <Element data={item} key={index} />)
return (
<div>
{renderedOutput}
</div>
);
}

componentDidMount() {
window.addEventListener('scroll', this.handleScroll.bind(this))
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll.bind(this))
}
handleScroll(event) {
var visibleStart = Math.floor($(window).scrollTop()/100);
var visibleEnd = visibleStart + 20;
var nextListItem = [...arr.slice(visibleStart, visibleEnd)];
console.log(visibleStart + " " + visibleEnd);
this.setState({
visibleStart: visibleStart,
visibleEnd: visibleEnd,
listItems: [...this.state.listItems, ...nextListItem]
});

}

}
ReactDOM.render(<List />, document.getElementById("app"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>React Infinite Scroll</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

最新更新