简而言之,
我有一个无限滚动列表,为每个Item 5 PureComponent渲染。
我的想法是以某种方式,只有在项目可见时才渲染5 PureComponent。
问题是,
如何检测Item组件是否对用户可见?
答案 0 :(得分:1)
最简单的解决方案:
将scrollPosition
和containerSize
添加到this.state
在ref
render()
<div ref={cont => { this.scrollContainer = cont; }} />
componentDidMount()
中的订阅scroll
事件
this.scrollContainer.addEventListener('scroll', this.handleScroll)
在componentWillUnmount()
取消订阅
this.scrollContainer.removeEventListener('scroll', this.handleScroll)
你的handleScroll
应该看起来像
handleScroll (e) {
const { target: { scrollTop, clientHeight } } = e;
this.setState(state => ({...state, scrollPosition: scrollTop, containerSize: clientHeight}))
}
然后在你的渲染函数中,只检查应该显示哪个元素并渲染正确的元素numOfElementsToRender = state.containerSize / elementSize
和firstElementIndex = state.scrollPosition / elementSize - 1
当你拥有所有这些时,只需渲染你的元素列表并在元素的index
上应用过滤器,或者你想要对它们进行排序
Ofc你需要处理所有边缘情况并添加bufor以实现平滑滚动(20%的高度应该没问题)
答案 1 :(得分:1)
您可以将IntersectionObserver API与polyfill(它的chrome 61+)一起使用。寻找交叉点是一种更高效的方式(在新的浏览器中),在其他情况下,它会回到piro的答案。它们还允许您指定交叉点变为真的阈值。看看这个:
https://github.com/researchgate/react-intersection-observer
import React from 'react';
import 'intersection-observer'; // optional polyfill
import Observer from '@researchgate/react-intersection-observer';
class ExampleComponent extends React.Component {
handleIntersection(event) {
console.log(event.isIntersecting); // true if it gets cut off
}
render() {
const options = {
onChange: this.handleIntersection,
root: "#scrolling-container",
rootMargin: "0% 0% -25%"
};
return (
<div id="scrolling-container" style={{ overflow: 'scroll', height: 100 }}>
<Observer {...options}>
<div>
I am the target element
</div>
</Observer>
</div>
);
}
}