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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:45:55