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

Next.js 实现回到顶部按钮无法正确获取滚动位置问题求助

问题解决方案

你的问题根源是滚动行为没有发生在浏览器窗口上,而是你自定义的容器元素内部:
你给Base组件的根div设置了h-screen(高度等于设备视口高度)和overflow-y: auto属性,相当于把整个页面的滚动区域限制在了这个div内部,window本身不存在滚动,所以读取window.scrollY、监听window的scroll事件都不会得到正确结果。

修复步骤

  • 给滚动容器div绑定React ref,用来访问真实DOM节点
  • 把scroll事件监听器绑定到这个容器DOM上,而非window
  • 滚动位置读取容器的scrollTop属性,而非window.scrollY
  • 回到顶部方法调用容器的scrollTo方法,而非window的同名方法
  • 给useEffect添加空依赖数组,避免重复绑定事件导致性能问题

修复后代码示例

import { useState, useEffect, useRef } from 'react';

const Base = () => {
  const [showButton, setShowButton] = useState(false);
  // 给滚动容器加ref
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  const handleScroll = () => {
    // 读取容器的scrollTop
    if (scrollContainerRef.current?.scrollTop > 300) {
      setShowButton(true);
    } else {
      setShowButton(false);
    }
  };

  useEffect(() => {
    const container = scrollContainerRef.current;
    if (!container) return;
    // 给容器绑定滚动事件
    container.addEventListener('scroll', handleScroll, true);
    return () => container.removeEventListener('scroll', handleScroll, true);
  }, []); // 空依赖仅在组件挂载/卸载时执行一次

  const scrollToTop = () => {
    // 调用容器的滚动方法
    scrollContainerRef.current?.scrollTo(0, 0);
  };

  return (
    // 给div绑定ref
    <div ref={scrollContainerRef} className="antialiased text-gray-600 h-screen w-screen flex flex-col overflow-y-auto">
      {/* 其余原有组件内容 */}
      {showButton && <button onClick={scrollToTop}>回到顶部</button>}
    </div>
  );
};

内容的提问来源于stack exchange,提问作者Nikola-Milovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 19:39:01