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

如何用React实现滚动时导航栏固定在顶部?

React实现滚动时导航栏固定顶部

方案一:React Hooks + 滚动监听(对应原生JS逻辑)

React中不建议直接操作DOM,我们可以通过useRef获取导航栏元素,useState控制固定状态,配合useEffect添加/移除滚动监听:

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

const Navbar = () => {
  const [isSticky, setIsSticky] = useState(false);
  // 用于获取导航栏DOM元素
  const navbarRef = useRef(null);

  useEffect(() => {
    const handleScroll = () => {
      if (!navbarRef.current) return;
      // 获取导航栏初始偏移量
      const navbarOffsetTop = navbarRef.current.offsetTop;
      // 根据滚动位置更新状态
      setIsSticky(window.pageYOffset >= navbarOffsetTop);
    };

    // 添加滚动监听
    window.addEventListener('scroll', handleScroll);
    // 组件卸载时移除监听,避免内存泄漏
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    // 根据状态动态添加sticky类
    <nav ref={navbarRef} className={`navbar ${isSticky ? 'sticky' : ''}`}>
      <ul>
        <li>首页</li>
        <li>关于我们</li>
        <li>联系我们</li>
      </ul>
    </nav>
  );
};

export default Navbar;

对应的CSS样式:

.navbar {
  width: 100%;
  padding: 1rem 2rem;
  background-color: #ffffff;
  /* 可选:添加初始阴影 */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.sticky {
  position: fixed;
  top: 0;
  left: 0;
  /* 固定后增强阴影,区分内容 */
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
  z-index: 100; /* 确保导航栏在内容上方 */
}

性能优化:添加防抖

滚动事件触发频率极高,添加防抖函数可以减少状态更新次数,提升性能:

// 防抖工具函数
const debounce = (func, delay = 100) => {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
};

// 修改useEffect中的监听逻辑
useEffect(() => {
  const handleScroll = debounce(() => {
    if (!navbarRef.current) return;
    const navbarOffsetTop = navbarRef.current.offsetTop;
    setIsSticky(window.pageYOffset >= navbarOffsetTop);
  });

  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

方案二:纯CSS实现(更简洁)

如果不需要兼容旧版浏览器(IE不支持),可以直接使用CSS的position: sticky,无需JS逻辑:

.navbar {
  position: sticky;
  top: 0;
  width: 100%;
  padding: 1rem 2rem;
  background-color: #ffffff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
  z-index: 100;
}

注意:使用position: sticky时,父元素不能设置overflow: hidden、overflow: auto等属性,否则粘性定位会失效。

常见失败原因分析

  • 直接操作DOM:React组件重渲染时,DOM元素可能被重新创建,原生JS的监听会失效;
  • 过早获取offsetTop:组件未挂载完成就获取元素偏移量,导致值为0;
  • 未清理监听:组件卸载后滚动监听未移除,可能引发内存泄漏或异常。

内容的提问来源于stack exchange,提问作者Sahil verma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:05:19