React文章阅读进度条函数始终显示0值的问题求助
解决滚动进度始终显示0的问题
问题分析
你的代码始终显示0,大概率是以下两个原因之一:
- 滚动事件绑定到了
window,但实际滚动的是页面内的某个容器(比如带overflow: auto的文章容器),导致document.documentElement.scrollTop始终为0 - 页面内容还没加载完成时,
document.documentElement.scrollHeight - documentElement.clientHeight的结果为0,除以0后得到NaN,最终进度被设为0
解决方案
1. 针对容器内滚动的情况
如果文章是在独立容器中滚动,需要给容器添加ref并监听其滚动事件:
import { useState, useEffect, useRef } from 'react' function ArticleProgress() { const [scrollTop, setScrollTop] = useState(0) const articleRef = useRef(null) const onScroll = () => { if (!articleRef.current) return const container = articleRef.current const winScroll = container.scrollTop const height = container.scrollHeight - container.clientHeight // 避免除以0的情况 if (height === 0) { setScrollTop(0) return } const scrolled = (winScroll / height) * 100 setScrollTop(scrolled) } useEffect(() => { const container = articleRef.current if (!container) return container.addEventListener('scroll', onScroll) return () => container.removeEventListener('scroll', onScroll) }, []) return ( <div> <div className="progress-bar" style={{ width: `${scrollTop}%` }}></div> <div ref={articleRef} className="article-container" style={{ height: '80vh', overflow: 'auto' }} > {/* 文章内容 */} </div> </div> ) }
2. 针对全局滚动的情况
如果确实是全局滚动,需要处理内容未加载完成的情况,同时优化事件监听的依赖:
import { useState, useEffect, useCallback } from 'react' function GlobalProgress() { const [scrollTop, setScrollTop] = useState(0) // 用useCallback包裹,避免每次渲染创建新函数 const onScroll = useCallback(() => { const documentEl = document.documentElement const winScroll = documentEl.scrollTop const height = documentEl.scrollHeight - documentEl.clientHeight if (height === 0) { setScrollTop(0) return } const scrolled = (winScroll / height) * 100 setScrollTop(scrolled) }, []) useEffect(() => { window.addEventListener('scroll', onScroll) return () => window.removeEventListener('scroll', onScroll) }, [onScroll]) return ( <div className="progress-bar" style={{ position: 'fixed', top: 0, left: 0, height: '4px', backgroundColor: 'blue', width: `${scrollTop}%` }}></div> ) }
额外注意点
- 确保滚动容器设置了正确的
overflow属性(比如overflow: auto或overflow-y: scroll),否则不会触发滚动事件 - 如果文章内容是异步加载的,可以在内容加载完成后重新计算一次进度,比如在
useEffect中监听内容的加载状态
内容的提问来源于stack exchange,提问作者IvonaK
相关产品推荐
相关产品推荐

