Jquery滚动进度条代码转换为React下Vanilla JS时Math.round返回NaN问题
问题排查与修复方案
错误原因定位
NaN问题是核心变量取值错误导致除法运算出现非数值结果:
window.onscroll是滚动事件绑定属性,不是当前页面滚动距离,正确取值为window.scrollY(兼容所有现代浏览器)document不存在offsetHeight属性,整个文档的总高度应取document.documentElement.scrollHeightwindow不存在offsetHeight属性,浏览器视口高度应取window.innerHeight
同时存在两处和原jQuery逻辑不匹配的问题:
- 原代码是给
.fill设置高度,改写代码错误改为设置innerHTML - 原代码
h1使用textColor、.fill背景使用bgColor,改写代码把颜色赋值逻辑搞反
修复后的原生JS版本(仅对齐原jQuery逻辑)
const progress = () => { const windowScrollTop = window.scrollY; const docHeight = document.documentElement.scrollHeight; const windowHeight = window.innerHeight; // 处理文档高度小于视口高度时,分母为负/0的边界情况 const scrollableHeight = docHeight - windowHeight; const progressPercent = scrollableHeight <= 0 ? 100 : (windowScrollTop / scrollableHeight) * 100; const bgColor = progressPercent > 99 ? "#fff" : "#fff"; const textColor = progressPercent > 99 ? "#fff" : "#333"; document.querySelector("h1").innerHTML = Math.round(progressPercent) + "%"; document.querySelector("h1").style.color = textColor; document.querySelector(".fill").style.height = progressPercent + "%"; document.querySelector(".fill").style.backgroundColor = bgColor; } // 绑定滚动事件,否则仅页面加载时执行一次 window.addEventListener('scroll', progress); progress();
React项目推荐写法(避免直接操作DOM)
React生态下更推荐用状态管理进度值,不要直接查询操作DOM:
import { useState, useEffect } from 'react'; const ProgressBar = () => { const [progress, setProgress] = useState(0); useEffect(() => { const handleScroll = () => { const windowScrollTop = window.scrollY; const docHeight = document.documentElement.scrollHeight; const windowHeight = window.innerHeight; const scrollableHeight = docHeight - windowHeight; const currentProgress = scrollableHeight <= 0 ? 100 : (windowScrollTop / scrollableHeight) * 100; setProgress(Math.round(currentProgress)); }; window.addEventListener('scroll', handleScroll); handleScroll(); // 初始化进度 return () => window.removeEventListener('scroll', handleScroll); // 组件卸载时清除事件 }, []); const textColor = progress > 99 ? "#fff" : "#333"; const fillBgColor = progress > 99 ? "#fff" : "#fff"; return ( <div className="progress-container"> <h1 style={{ color: textColor }}>{progress}%</h1> <div className="fill" style={{ height: `${progress}%`, backgroundColor: fillBgColor }} /> </div> ); }; export default ProgressBar;
内容的提问来源于stack exchange,提问作者jricc russel
相关产品推荐
相关产品推荐

