如何用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
相关产品推荐
相关产品推荐

