React中Styled-Components下拉列表动画与层级问题咨询
问题解答
1. 实现下拉列表收起时的渐变动画
当前通过条件渲染直接卸载StyledDropdown组件,导致收起时没有时间执行动画。解决核心是保留组件DOM直到动画完成,通过状态控制动画状态:
修改思路
- 新增
isAnimating状态跟踪动画过程 - 分别定义展开/收起的关键帧动画,通过
dropDownVisible控制动画方向 - 收起时先触发动画,延迟到动画结束后再隐藏组件
关键代码修改
// 定义双向动画关键帧 const dropDownAnimation = keyframes` from { transform: translateY(-300px); opacity: 0; } to { transform: translateY(0); opacity: 1; } `; const dropUpAnimation = keyframes` from { transform: translateY(0); opacity: 1; } to { transform: translateY(-300px); opacity: 0; } `; // 给下拉组件添加动画控制 const StyledDropdown = styled.div<{ isVisible: boolean }>` width: 100px; height: 300px; background-color: #d9d9d9; border-radius: 0px 0px 10px 10px; z-index: 3; position: relative; animation: ${props => props.isVisible ? dropDownAnimation : dropUpAnimation} 1s forwards; `; // 组件内状态与逻辑调整 const AApage = () => { const [dropDownVisible, setDropDownVisible] = useState<boolean>(false); const [isAnimating, setIsAnimating] = useState<boolean>(false); const toggleDropDownVisible = () => { if (dropDownVisible) { setIsAnimating(true); // 等待动画结束后更新状态 setTimeout(() => { setDropDownVisible(false); setIsAnimating(false); }, 1000); } else { setDropDownVisible(true); } }; // 渲染时保留组件直到动画完成 return ( <> {/* 头部内容不变 */} {(dropDownVisible || isAnimating) && ( <StyledDropdown isVisible={dropDownVisible}> <div>temp data</div> <div>temp data</div> <div>temp data</div> </StyledDropdown> )} </> ); };
2. z-index不生效导致StyledHead被遮挡的原因
z-index属性仅对定位元素生效(即position值为relative、absolute、fixed或sticky)。当前StyledHead和StyledDropdown默认是position: static,所以设置的z-index完全不起作用。
修改方案
给两个Styled组件添加position: relative:
const StyledHead = styled.div` width: 100px; height: 100px; background-color: red; z-index: 11; position: relative; // 新增定位属性 `; const StyledDropdown = styled.div<{ isVisible: boolean }>` width: 100px; height: 300px; background-color: #d9d9d9; border-radius: 0px 0px 10px 10px; z-index: 3; position: relative; // 新增定位属性 // 其他样式不变 `;
完整修改后的代码
// AApage.jsx import { useState } from 'react'; import { MdArrowDropDown, MdArrowDropUp } from 'react-icons/md'; import styled, { keyframes } from 'styled-components'; const dropDownAnimation = keyframes` from { transform: translateY(-300px); opacity: 0; } to { transform: translateY(0); opacity: 1; } `; const dropUpAnimation = keyframes` from { transform: translateY(0); opacity: 1; } to { transform: translateY(-300px); opacity: 0; } `; const StyledHead = styled.div` width: 100px; height: 100px; background-color: red; z-index: 11; position: relative; `; const StyledDropdown = styled.div<{ isVisible: boolean }>` width: 100px; height: 300px; background-color: #d9d9d9; border-radius: 0px 0px 10px 10px; z-index: 3; position: relative; animation: ${props => props.isVisible ? dropDownAnimation : dropUpAnimation} 1s forwards; `; const AApage = () => { const [dropDownVisible, setDropDownVisible] = useState<boolean>(false); const [isAnimating, setIsAnimating] = useState<boolean>(false); const toggleDropDownVisible = () => { if (dropDownVisible) { setIsAnimating(true); setTimeout(() => { setDropDownVisible(false); setIsAnimating(false); }, 1000); } else { setDropDownVisible(true); } }; return ( <> <StyledHead> <div>Dropdown</div> <span>{`${dropDownVisible}`}</span> {dropDownVisible ? ( <MdArrowDropUp onClick={toggleDropDownVisible} /> ) : ( <MdArrowDropDown onClick={toggleDropDownVisible} /> )} </StyledHead> {(dropDownVisible || isAnimating) && ( <StyledDropdown isVisible={dropDownVisible}> <div>temp data</div> <div>temp data</div> <div>temp data</div> </StyledDropdown> )} </> ); }; export default AApage;
内容的提问来源于stack exchange,提问作者shinbian11
相关产品推荐
相关产品推荐

