React中window.scrollTo()实现返回顶部连续点击位置异常问题
解决React返回顶部按钮连续点击卡顿问题
问题根源
连续点击卡顿主要来自两个点:
<a>标签自带的默认导航行为,哪怕没写href,浏览器仍会触发默认事件干扰滚动逻辑- 每次点击都直接调用
window.scrollTo,连续点击会中断浏览器正在执行的滚动操作,导致滚动过程被打断、卡住
修复方案
1. 先阻止<a>标签的默认行为
在点击事件里加入e.preventDefault(),避免浏览器默认行为干扰:
render() { return ( <a className="fs-1 screen-button" id="Button_Back_Top" style={{ display: "block" }} onClick={(e) => { e.preventDefault(); // 阻止默认导航行为 this.Back_Top(); }} > <i className="bi bi-arrow-up-circle-fill"></i> </a> ) }
2. 控制滚动状态,防止重复触发
添加React状态标记是否正在滚动,滚动过程中禁用按钮点击,避免连续触发:
constructor(props) { super(props); this.state = { isScrolling: false }; } Back_Top() { if (this.state.isScrolling) return; // 正在滚动则直接返回,不重复执行 this.setState({ isScrolling: true }); window.scrollTo({ top: 0, behavior: 'smooth' // 开启平滑滚动,提升体验 }); // 滚动结束后恢复按钮可点击状态,时间可根据页面长度调整 setTimeout(() => { this.setState({ isScrolling: false }); }, 1000); } render() { return ( <a className="fs-1 screen-button" id="Button_Back_Top" style={{ display: "block", pointerEvents: this.state.isScrolling ? 'none' : 'auto' }} onClick={(e) => { e.preventDefault(); this.Back_Top(); }} > <i className="bi bi-arrow-up-circle-fill"></i> </a> ) }
3. 进阶优化:用scroll事件精准监听滚动结束
如果setTimeout的时间不好把控,可以通过监听scroll事件判断滚动是否真正停止:
constructor(props) { super(props); this.state = { isScrolling: false }; this.scrollEndTimer = null; } componentDidMount() { window.addEventListener('scroll', this.handleScrollEnd); } componentWillUnmount() { window.removeEventListener('scroll', this.handleScrollEnd); clearTimeout(this.scrollEndTimer); } handleScrollEnd = () => { clearTimeout(this.scrollEndTimer); // 滚动停止100ms后,标记滚动结束 this.scrollEndTimer = setTimeout(() => { this.setState({ isScrolling: false }); }, 100); } Back_Top() { if (this.state.isScrolling) return; this.setState({ isScrolling: true }); window.scrollTo({ top: 0, behavior: 'smooth' }); }
这样处理后,连续点击按钮就不会再出现卡顿,同时还能优化滚动的用户体验。
内容的提问来源于stack exchange,提问作者ChaCha
相关产品推荐
相关产品推荐

