我正在寻找如何加载区块的帮助,当用户滚动条并到达特定的div时,它应该运行一次函数,但代码运行多次:
async function loadMore(){
console.log('i load more');
}
window.addEventListener('scroll', async (event) => {
const {
scrollTop,
scrollHeight,
clientHeight
} = document.documentElement;
if (scrollTop + clientHeight >= scrollHeight - 1 ) {
document.getElementById('final').style.height = '3000px'
let msg = await loadMore()
console.log('i finish')
document.getElementById('final').style.height = '30px'
}
}, {
passive: true
});
return (
<div id='final'>
<Image src="/ajax-loader.gif" width={60} height={60} alt="loader spinner"></Image>
</div>
)
很少有东西:
- 您应该在
useEffect
中添加窗口事件侦听器。- 如果在组件的渲染阶段添加事件侦听器,它将在每次渲染时运行add-event侦听器,这可能是它多次运行的原因之一
- 您还需要像清理
useEffect
一样清理事件侦听器,否则您将再次获得大量事件侦听器
- 你需要解除onScroll处理程序的抖动
- 滚动事件会在您滚动时触发多次,这可能是您不想要的。因此,添加反跳将有助于减少用户滚动时调用处理程序的次数
- Lodash的debounce是
debounce
的一个流行实现。如果您想要或创建自己的实现,您可以选择其他实现
import debounce from "lodash.debounce";
function YourComponent() {
async function loadMore(){
console.log('i load more');
}
// "useEffect" so that you don't add a new event listener
// on every render
useEffect(() => {
const onScroll = async (event) => {
// Whatever you want to do when user scrolls
}
// This is the debounced "onScroll" function instance
// "500" specifies that it will be debounced for 500 milliseconds
const debouncedOnScroll = debounce(onScroll, 500);
// Attach the event listener to window
window.addEventListener('scroll', debouncedOnScroll);
// Cleanup the event listener when component unmounts or
// when the "useEffect" runs again.
return () => window.removeEventListener('scroll', debouncedOnScroll);
}, []);
return (
<div id='final'>
{/* Rest of your JSX */}
</div>
)
}
触发useEffect
内的窗口事件侦听器
确保清除事件:return () => window.removeEventListener('scroll', callback);