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

如何在React中实现滚动时的头部导航栏动画效果?

解决React中滚动触发导航栏样式变化的问题

问题说明

我正在复刻一个Codepen模板到React中,需要把这段jQuery实现的滚动效果转成React代码:

$(window).scroll(function () {
  if ($(document).scrollTop() > 50) {
    $(".nav").addClass("affix");
    console.log("OK");
  } else {
    $(".nav").removeClass("affix");
  }
});

以下是我目前的React代码,不确定如何实现滚动到一定距离时触发CSS类变化的效果:

import { useRef, useState } from "react";
import "./Navbar1.css";
import QueensLogoH from "./NavbarAssets/queens-logo-horizontal.png";

export default function App() {
  const [isActive, setIsActive] = useState(false);
  const mainListDivRef = useRef(null);

  function onClickNavTrigger() {
    setIsActive((a) => !a);
    const mainListDivEl = mainListDivRef.current;
    mainListDivEl.classList.toggle("show_list");
  }

  return (
    <>
      <nav className="nav">
        <div className="container">
          <div className="logo">
            <a href="#">
              <img src={QueensLogoH} height="80"></img>
            </a>
          </div>
          <div id="mainListDiv" className="main_list" ref={mainListDivRef}>
            <ul className="navlinks">
              <li>
                <a href="#">About</a>
              </li>
              <li>
                <a href="#">Portfolio</a>
              </li>
              <li>
                <a href="#">Services</a>
              </li>
              <li>
                <a href="#">Contact</a>
              </li>
            </ul>
          </div>
          <span className={`navTrigger ${isActive ? "active" : ""}`} onClick={onClickNavTrigger}>
            <i></i>
            <i></i>
            <i></i>
          </span>
        </div>
      </nav>

      <section className="home"></section>
      <div style={{ height: "1000px" }}>
        <h2 className="myH2">What is this ?</h2>
        <p className="myP">This is a responsive fixed navbar animated on scroll</p>
        <p className="myP">
          I took inspiration from ABDO STEIF and Dicson
        </p>
        <p className="myP">I HOPE YOU FIND THIS USEFULL</p>
        <p className="myP">Albi</p>
        <p className="myP">random text</p>
      </div>
    </>
  );
}

解决方案

通过React的状态管理和副作用监听即可实现该效果,步骤如下:

  1. 新增状态变量管理导航栏状态
    添加isNavAffixed状态,标记是否需要给导航栏添加affix类:
const [isNavAffixed, setIsNavAffixed] = useState(false);
  1. 使用useEffect监听滚动事件
    组件挂载时添加滚动监听,判断滚动距离并更新状态;组件卸载时移除监听避免内存泄漏:
useEffect(() => {
  const handleScroll = () => {
    const shouldAffix = window.scrollY > 50;
    setIsNavAffixed(shouldAffix);
    if (shouldAffix) console.log("OK");
  };

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

注意需要导入useEffect:import { useRef, useState, useEffect } from "react";

  1. 动态绑定导航栏的className
    将导航栏的className改为动态拼接,根据状态决定是否添加affix类:
<nav className={`nav ${isNavAffixed ? 'affix' : ''}`}>

修改后的完整代码

import { useRef, useState, useEffect } from "react";
import "./Navbar1.css";
import QueensLogoH from "./NavbarAssets/queens-logo-horizontal.png";

export default function App() {
  const [isActive, setIsActive] = useState(false);
  const [isNavAffixed, setIsNavAffixed] = useState(false);
  const mainListDivRef = useRef(null);

  function onClickNavTrigger() {
    setIsActive((a) => !a);
    const mainListDivEl = mainListDivRef.current;
    mainListDivEl.classList.toggle("show_list");
  }

  useEffect(() => {
    const handleScroll = () => {
      const shouldAffix = window.scrollY > 50;
      setIsNavAffixed(shouldAffix);
      if (shouldAffix) console.log("OK");
    };

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

  return (
    <>
      <nav className={`nav ${isNavAffixed ? 'affix' : ''}`}>
        <div className="container">
          <div className="logo">
            <a href="#">
              <img src={QueensLogoH} height="80"></img>
            </a>
          </div>
          <div id="mainListDiv" className="main_list" ref={mainListDivRef}>
            <ul className="navlinks">
              <li>
                <a href="#">About</a>
              </li>
              <li>
                <a href="#">Portfolio</a>
              </li>
              <li>
                <a href="#">Services</a>
              </li>
              <li>
                <a href="#">Contact</a>
              </li>
            </ul>
          </div>
          <span className={`navTrigger ${isActive ? "active" : ""}`} onClick={onClickNavTrigger}>
            <i></i>
            <i></i>
            <i></i>
          </span>
        </div>
      </nav>

      <section className="home"></section>
      <div style={{ height: "1000px" }}>
        <h2 className="myH2">What is this ?</h2>
        <p className="myP">This is a responsive fixed navbar animated on scroll</p>
        <p className="myP">
          I took inspiration from ABDO STEIF and Dicson
        </p>
        <p className="myP">I HOPE YOU FIND THIS USEFULL</p>
        <p className="myP">Albi</p>
        <p className="myP">random text</p>
      </div>
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:39:17