styled-components基于Props实现双向动画:首屏加载动画异常问题
解决首次加载触发slideOut动画的问题
我明白你的困扰——页面刚加载时,MainContentBox就自动执行了slideOutContent动画,但你只想在侧边栏开关切换时才触发动画。这个问题的根源在于组件首次渲染时,slide prop是false,styled-components直接应用了slideOutContent动画,而这个动画的起始值是margin-left:256px,浏览器会默认从这个值过渡到0,导致了不必要的初始动画。
下面给你一个简单有效的解决方案,不需要引入额外依赖:
步骤1:调整Styled组件,分离初始样式与动画逻辑
我们先给组件设置初始的静态样式(匹配slide=false的状态),然后只在需要动画的时候才添加动画规则:
import styled, { keyframes } from 'styled-components'; const slideInContent = keyframes` from { margin-left: 0; } to { margin-left: 256px; } `; const slideOutContent = keyframes` from { margin-left: 256px; } to { margin-left: 0; } `; const MainContentBox = styled.div.attrs(props => ({ // 初始样式直接匹配当前slide状态,无动画 style: { marginLeft: props.slide ? '256px' : '0', }, }))` // 只有当animate为true时,才启用动画 ${props => props.animate && ` animation: ${props.slide ? slideInContent : slideOutContent} forwards; animation-duration: 0.5s; animation-timing-function: linear; `} `;
步骤2:修改页面组件,控制动画启用时机
我们添加一个animate状态,标记是否已经触发过侧边栏切换——初始时设为false,第一次切换后改为true,这样就不会在首次加载时执行动画:
class PageWithDrawer extends React.Component { constructor(props) { super(props); this.state = { open: false, animate: false // 初始不启用动画 }; } toggleMenu = () => { this.setState(state => ({ open: !state.open, animate: true // 第一次切换后,永久启用动画 })); } render() { // ...其他页面内容 return ( <div> {/* ...侧边栏组件 */} <MainContentBox slide={this.state.open} animate={this.state.animate}> {this.props.children} </MainContentBox> </div> ); } }
原理说明
- 首次加载时,
animate是false,组件直接应用margin-left:0的静态样式,没有动画,符合预期。 - 第一次点击侧边栏开关后,
animate变为true,之后每次切换open状态时,都会触发对应的slideIn或slideOut动画,完全符合你的需求。
如果你的项目已经升级到React函数组件,也可以用useState和useEffect来实现类似逻辑,核心思路都是让初始渲染时不加载动画规则,只在状态切换时启用。
内容的提问来源于stack exchange,提问作者Tzook Bar Noy
相关产品推荐
相关产品推荐

