近期要实现一个滚动加载的列表组件,很明显可以通过绑定滚动事件来监听是否滚动到底部,每次滚动到底部的时候执行加载,然后添加新一页的列表数据就可以了。
与滚动最为相关的属性是 scrollTop属性,即滚动条滚动的距离。很明显,我们只要知道滚动区域的实际长度和滚动容器的长度,滚动到底部的时候有这样的等式
滚动条滚动长度+容器长度=内容长度
而容器长度也就是offsetHeight 当前元素的高度,内容长度,也就是scrollHeight
所以也就是 e.target.scrollHeight - e.target.scrollTop - e.target.offsetHeight=0
我们把这个核心逻辑封装成自定义hook,这样以后就可以直接调用这个代码
import { useEffect } from 'react'
/**
* 滚动到底部触发事件的hook
* @param listDomRef 绑定滚动事件的dom节点的ref
* @param callback 滚动到底部时执行的callback
* @param reactionDistance 距离底部的触发距离,默认为0
*/
export const useScrollToBottomHook = (
listDomRef: any,
callback: () => void,
reactionDistance = 0
) => {
useEffect(() => {
const currentDom = listDomRef.current
const handleScroll = (e: any) => {
if (
e.target.scrollHeight - e.target.scrollTop - e.target.offsetHeight <=
reactionDistance
) {
callback()
}
}
currentDom!.addEventListener('scroll', handleScroll)
return () => {
// 组件销毁时清除绑定事件
currentDom!.removeEventListener('scroll', handleScroll)
}
}, [callback, reactionDistance, listDomRef])
}