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

如何用React实现侧边栏随页面滚动淡入淡出效果?

解决方案

你的代码存在几个核心问题:滚动逻辑反转、无节流/延迟控制、缺少过渡动画,以下是修正后的完整实现:

1. 核心逻辑修正

  • 向下滚动(window.scrollY > lastScrollY)时触发淡入,向上滚动时触发淡出
  • 添加节流函数避免滚动事件频繁触发
  • 用定时器实现延迟效果,防止滚动时频繁切换状态

2. 完整代码实现

import React, { useState, useEffect, useRef } from "react";

const Navbar = () => {
  const [show, setShow] = useState(false);
  const [lastScrollY, setLastScrollY] = useState(0);
  const timeoutRef = useRef(null); // 用于存储延迟定时器

  // 节流函数:限制事件触发频率
  const throttle = (func, delay) => {
    let lastCall = 0;
    return (...args) => {
      const now = Date.now();
      if (now - lastCall >= delay) {
        lastCall = now;
        func(...args);
      }
    };
  };

  const controlNavbar = () => {
    if (typeof window === "undefined") return;

    // 清除之前的定时器,避免冲突
    if (timeoutRef.current) clearTimeout(timeoutRef.current);

    if (window.scrollY > lastScrollY) {
      // 向下滚动:延迟淡入
      timeoutRef.current = setTimeout(() => setShow(true), 200);
    } else {
      // 向上滚动:延迟淡出
      timeoutRef.current = setTimeout(() => setShow(false), 200);
    }

    setLastScrollY(window.scrollY);
  };

  useEffect(() => {
    const throttledControl = throttle(controlNavbar, 100); // 100ms节流间隔
    window.addEventListener("scroll", throttledControl);

    return () => {
      window.removeEventListener("scroll", throttledControl);
      if (timeoutRef.current) clearTimeout(timeoutRef.current);
    };
  }, [lastScrollY]);

  return (
    <div>
      <nav className={`transition-opacity duration-500 ${show ? "opacity-100" : "opacity-0"}`}>
        <div className="invisible md:visible">
          <aside className="w-64" aria-label="Sidebar">
            <div className="overflow-y-auto py-4 px-3 bg-gray-50 border-r-2 border-black dark:bg-white h-screen">
              <ul className="space-y-2">
                <li>
                  <a className="flex items-center py-5 p-2 pl-12 text-xl font-normal text-gray-900 rounded-lg dark:text-red-500 hover:bg-gray-100 dark:hover:bg-gray-700">
                    <span className="flex-1 ml-3 whitespace-nowrap">Home</span>
                  </a>
                </li>
                <li>
                  <a className="flex items-center py-2 p-2 pl-12 text-xl font-normal text-gray-900 rounded-lg dark:text-red-500 hover:bg-gray-100 dark:hover:bg-gray-700">
                    <span className="flex-1 ml-3 whitespace-nowrap">Projects</span>
                  </a>
                </li>
              </ul>
            </div>
          </aside>
        </div>
      </nav>
    </div>
  );
};

export default Navbar;

3. 关键改进点

  • 节流函数:减少滚动事件触发次数,提升性能
  • 延迟定时器:通过setTimeout实现滚动后的延迟切换,避免状态频繁跳动
  • CSS过渡:用Tailwind的transition-opacity duration-500实现平滑淡入淡出
  • 修正逻辑:将向下/向上滚动的状态切换逻辑调整正确
  • 类名统一:把所有class改为React规范的className
  • 清理定时器:在组件卸载时清除定时器,避免内存泄漏

4. 自定义调整建议

  • 修改setTimeout的延迟时间(当前200ms)来控制响应延迟
  • 调整duration-500来改变淡入淡出的动画时长
  • 如果需要配合位移动画,可以添加transform过渡(比如translate-x-0和translate-x-full)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:10:54