功能简介
useReachBottom
是一个 React 自定义 Hook,支持监听页面(body)或任意可滚动元素(如 div)是否滚动到底部。它能帮助你在用户滑动到底部时触发加载更多、显示提示等操作,极大提升前端交互体验。
亮点
- 通用性强:支持监听整个页面,也支持监听任意传入的滚动容器。
- 兼容性好:内部对 scrollTop/scrollHeight 取值做了兼容处理,适配主流浏览器。
- 易用性高:API 简单,直接返回是否到底部的布尔值。
- 可自定义偏移:支持 offset 参数,灵活控制触发时机。
- 无第三方依赖:纯 React 实现,体积小巧。
使用场景
- 无限滚动加载:用户滑动到底部时自动加载更多内容。
- 滚动提示:如“已到页面底部”提示条。
- 局部滚动区域监听:如聊天窗口、评论区、弹窗等自定义滚动容器。
- 数据上报:统计用户是否浏览到页面底部。
使用示例
1. 监听页面(body)滚动到底部
import useReachBottom from "../hooks/useReachBottom";
function PageScrollDemo() {
const isBottom = useReachBottom();
return (
<div>
<div>{isBottom ? "已到页面底部" : "未到页面底部"}</div>
{/* 内容足够撑开页面高度 */}
{Array.from({ length: 20 }).map((_, i) => (
<div key={i}>内容 {i + 1}</div>
))}
</div>
);
}
2. 监听指定 div 元素滚动到底部
import { useRef } from "react";
import useReachBottom from "../hooks/useReachBottom";
function DivScrollDemo() {
const divRef = useRef();
const isBottom = useReachBottom(divRef);
return (
<div>
<div
ref={divRef}
style={{ height: 200, overflow: "auto", border: "1px solid #ccc" }}
>
{Array.from({ length: 10 }).map((_, i) => (
<div key={i}>行 {i + 1}</div>
))}
</div>
<div>{isBottom ? "已到div底部" : "未到div底部"}</div>
</div>
);
}
useReachBottom 源码
import { useEffect, useState } from "react";
export default function useReachBottom(targetRef = null, offset = 0) {
const [isBottom, setIsBottom] = useState(false);
useEffect(() => {
const element = targetRef?.current || document.documentElement;
function handleScroll() {
let scrollTop, scrollHeight, clientHeight;
if (targetRef?.current) {
scrollTop = element.scrollTop;
scrollHeight = element.scrollHeight;
clientHeight = element.clientHeight;
} else {
// 兼容所有主流浏览器
scrollTop = Math.max(
window.scrollY,
document.documentElement.scrollTop,
document.body.scrollTop
);
scrollHeight = Math.max(
document.documentElement.scrollHeight,
document.body.scrollHeight
);
clientHeight = window.innerHeight;
}
if (scrollHeight > clientHeight) {
setIsBottom(scrollTop + clientHeight >= scrollHeight - 2 - offset);
} else {
setIsBottom(false);
}
}
const scrollTarget = targetRef?.current || window;
scrollTarget.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
scrollTarget.removeEventListener("scroll", handleScroll);
};
}, [targetRef, offset]);
return isBottom;
}
原文链接:https://code.ifrontend.net/archives/757,转载请注明出处。
评论0