You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:41:18