我正在尝试确定在我的React组件中的onScroll
事件侦听器中提高性能的最佳方法。我有一个跟踪scrollY
的简单侦听器。为了跟踪此消息(跨浏览器),我具有以下内容:
handleScroll = (event) => {
let scrollTop = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop)
}
现在,我需要确定用户是向上滚动还是向下滚动。我希望实际的
event
对象具有某种标记,但是我大多数人看到有人建议跟踪以前的scrollTop
并与函数的每次迭代进行比较。我想知道,每次滚动句柄运行时调用
this.setState({scrollY: scrollTop})
会对性能产生什么影响?当我使用滚动条向下滚动页面时,事件处理程序将触发50-70次。我知道React.Component.setState
确实有一些异步/批处理行为-调用50次似乎太过分了。因此,我没有考虑调用
setState
,而是考虑将global variable
存储在组件中-我认为将单个var更新50次将没有太大影响。我也在考虑限制该功能,但是如果我希望它相对敏感并且不错过滚动事件,可以限制该功能吗?这基本上就是我想要做的:
// Global Variable ...
let avoidNameCollidePrevScrollTop
class WatchMeScroll extends Component {
handleScroll = (event) => {
let scrollTop = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop)
if (avoidNameCollidePrevScrollTop && scrollTop > avoidNameCollidePrevScrollTop && this.state.scrollDir !== 'Scrolling Down') {
this.setState({
scrollDir: 'Scrolling Down'
})
}
if (avoidNameCollidePrevScrollTop && scrollTop < avoidNameCollidePrevScrollTop && this.state.scrollDir !== 'Scrolling Up') {
this.setState({
scrollDir: 'Scrolling Up'
})
}
// { Handle UI changes by checking if user is scrolling Up/Down into different sections of the app using Ref.getBoundingClientRect() }
// Set ScrollTop position for next iteration of handleScroll - avoiding setState firing excessively
avoidNameCollidePrevScrollTop = scrollTop
}
}
最佳答案
是! setState()
是一个异步操作,但是在每次setState
调用之后,您的组件都会重新呈现,并且最终会在像滚动处理程序那样频繁调用时出现性能问题。
理想情况下,如果更改变量与更新DOM(更具体地说是虚拟DOM)无关,则不应将其保留为状态变量,而应使类变量像
constructor(props){
super(props);
this.someVar = someDefaultValue;
并且可以使用
someVar
在组件内部的任何位置访问此变量this.someVar
。