如何为React+TailwindCSS侧边栏添加关闭动画?
侧边栏关闭动画失效的解决方案
问题根源
当前实现中,侧边栏的渲染完全依赖sidebarOpen状态——当状态变为false时,组件直接从DOM中卸载,关闭动画根本没机会执行。另外,手动操作内联样式的方式也容易导致动画逻辑混乱。
优化方案
调整逻辑:先触发关闭动画,等动画执行完成后再移除侧边栏组件;同时用CSS类统一管理动画状态,替代繁琐的内联样式操作。
修改后的Menu组件代码
import React, { useRef, useState, useEffect } from 'react'; import Sidebar from "./Sidebar"; const Menu = ({ sidebarOpen, toggleSidebar }) => { const [showSidebar, setShowSidebar] = useState(sidebarOpen); const sidebarRef = useRef(null); // 同步外部传入的sidebarOpen状态 useEffect(() => { if (sidebarOpen) { setShowSidebar(true); document.body.classList.add("sidebar-open"); document.body.style.overflow = "hidden"; } else { // 触发关闭动画 if (sidebarRef.current) { sidebarRef.current.classList.add('sidebar-slide-out'); } document.body.style.overflow = "auto"; } }, [sidebarOpen]); // 监听关闭动画结束事件 useEffect(() => { const handleAnimationEnd = (e) => { if (e.propertyName === 'transform' && !sidebarOpen) { setShowSidebar(false); document.body.classList.remove("sidebar-open"); sidebarRef.current?.classList.remove('sidebar-slide-out'); } }; const sidebarEl = sidebarRef.current; if (sidebarEl) { sidebarEl.addEventListener('transitionend', handleAnimationEnd); } return () => { sidebarEl?.removeEventListener('transitionend', handleAnimationEnd); }; }, [sidebarOpen]); const handleToggleSidebar = () => { toggleSidebar(!sidebarOpen); }; return ( <div className="fixed bottom-0 left-0 w-full bg-white z-50 border-t-1 border-green-900"> <div className="h-[60px] flex items-center justify-between"> <div className="flex items-center ml-4"> <div className="cursor-pointer p-3" onClick={handleToggleSidebar} > <div className={`h-1 w-6 bg-green-700 rounded mb-1 ${sidebarOpen ? 'opacity-0' : ''}`}></div> <div className={`h-1 w-6 bg-green-700 rounded mb-1 ${sidebarOpen ? 'opacity-0' : ''}`}></div> <div className={`h-1 w-6 bg-green-700 rounded ${sidebarOpen ? 'opacity-0' : ''}`}></div> </div> </div> </div> {showSidebar && ( <> <div className="fixed top-0 left-0 right-0 bottom-0 z-0 bg-gray-700 opacity-50 transition-opacity duration-300" onClick={() => toggleSidebar(false)} ></div> <div ref={sidebarRef} className="fixed top-0 left-0 bottom-0 z-10 w-full max-w-[20rem] p-4 bg-white shadow-xl shadow-blue-gray-900/5 transform transition-transform duration-500 ease-in-out" > <Sidebar /> </div> </> )} </div> ); } export default Menu;
添加自定义CSS类
在全局CSS中添加以下样式定义关闭动画:
body.sidebar-open { overflow: hidden; } .sidebar-slide-out { transform: translateX(-100%); }
关键改进点
- 分离状态控制:用本地
showSidebar状态控制组件渲染,外部sidebarOpen状态只负责触发动画逻辑,确保动画完成后再卸载组件。 - CSS类管理动画:用Tailwind的
transition-transform和自定义类sidebar-slide-out实现动画,替代内联样式,逻辑更清晰。 - 监听动画结束事件:通过
transitionend事件准确捕捉动画完成时机,再更新状态隐藏组件。 - 优化遮罩层动画:给遮罩层添加
opacity过渡,让整体交互更流畅。
内容的提问来源于stack exchange,提问作者nikolaPantelic98
相关产品推荐
相关产品推荐

