如何使用React+styled-components实现下拉菜单箭头翻转切换动画?
实现方案
你只需要对现有代码做两处核心调整即可满足需求:
- 给箭头组件添加带过渡效果的翻转受控样式
- (可选优化)修复当前下拉内容过渡不生效的问题(现有写法直接条件渲染会导致元素直接挂载卸载,过渡动画无法触发)
完整修改后代码如下:
import "./styles.css"; import styled from "styled-components"; import React, { useState, useCallback } from "react"; import { ArrowDown } from "./ArrowDown"; const Item = styled.div<{ active?: boolean }>` height: 40px; width: 300px; padding: 0px 30px; &:hover { background: #fafbfb; } `; const DropMenu = styled.div` display: flex; align-items: center; justify-content: space-between; color: #899098; width: 100%; height: 100%; font-size: 14px; font-weight: bold; gap: 12px; :hover { color: gray; } div { display: flex; align-items: center; gap: 12px; } `; const DropText = styled.div` padding-left: 32px; `; // 新增:带翻转过渡的箭头样式组件 const StyledArrow = styled(ArrowDown)<{ isOpen: boolean }>` transition: transform 0.3s ease; transform: ${props => props.isOpen ? 'rotate(180deg)' : 'rotate(0deg)'}; `; // 新增:下拉容器样式,实现平滑展开收起 const DropContent = styled.div<{ isOpen: boolean }>` height: ${props => props.isOpen ? '80px' : '0'}; // 两个Item每个高40px,总高80px opacity: ${props => props.isOpen ? 1 : 0}; overflow: hidden; transition: all 0.3s ease; `; export const App = () => { const [visible, setVisible] = useState(false); const handleDropVisibleChange = useCallback(() => { setVisible((prevVisible) => !prevVisible); }, []); // 这里依赖可以清空,因为用了函数式更新 return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> <Item onClick={handleDropVisibleChange}> <DropMenu> <div> <span>Menu</span> </div> {/* 替换原来的ArrowDown为带受控状态的StyledArrow */} <StyledArrow isOpen={visible} /> </DropMenu> </Item> {/* 替换原来的条件渲染为受控样式的DropContent */} <DropContent isOpen={visible}> <Item> <DropMenu> <DropText>box1</DropText> </DropMenu> </Item> <Item> <DropMenu> <DropText>box2</DropText> </DropMenu> </Item> </DropContent> </div> ); }; export default App;
实现说明:
- 箭头翻转通过
transform: rotate实现,配合transition属性实现0.3s的平滑过渡效果,和目标交互体验一致 - 下拉容器不再直接条件渲染,改为通过控制高度、透明度实现平滑展开收起,避免元素挂载卸载导致过渡失效
- 箭头的翻转状态完全和
visible变量绑定,状态同步不会出现错位
内容的提问来源于stack exchange,提问作者yuturo
相关产品推荐
相关产品推荐

