在我的React应用程序中,我有一个菜单,其中包含每个项目的子菜单。只要单击该项目,子菜单就会滑入。发生这种情况时,菜单标题也会更改。我想为标题更改设置动画,以便有一个平滑的淡入淡出效果。考虑一下React组件的render方法内的以下代码片段:
render() {
// other code
return(
<div className={`title ${this.state.subMenu.isOpen ? `open` : ''}`}>
<div>{this.state.heading}</div> // this heading changes when the sub-menu opens/renders
</div>
)
}
CSS:
@keyframes fade {
0%,100% { opacity: 1 }
50% { opacity: 0 }
}
.title {
background : black;
color : white;
}
.title.open {
animation: fade 500ms ease-in-out;
}
此方法的问题在于,在状态更改后重新渲染组件之后将应用open
类,因此,动画在渲染新的标题之后开始。这样会产生闪烁效果。但是,我希望动画在状态更改开始后立即开始。我为此查看了react-transition-group,但似乎没有为这种情况提供所需的解决方案。在下面的代码中,CSSTransition
要求从DOM上安装和卸载其子代。在此期间,仅DOM元素的值(标题)会更改。
<CSSTransition
in={this.state.subMenu.isOpen}
timeout={500}
classNames="open">
<div className={`title ${subMenu.isOpen ? `open` : ''}`}>
<div>{this.state.heading}</div> // heading changes when the sub-menu opens
</div>
</CSSTransition>
有没有办法达到预期的结果?
您可以使用getSnapshotBeforeUpdate
,对其进行阅读here。
但是,如果您不能使用它,则可以在任何状态更改后希望具有副作用的情况下使用componentDidUpdate
。
我相信您指的是这样的闪烁
仅当状态属性(或道具)发生变化时才触发内部动画,因此动画仅在下一个渲染中开始。好吧,这与hooks
的执行方式有关。默认情况下,它是这样的
但是为什么要等待浏览器绘制?这样,您就不会阻塞线程,因为大多数效果不会触发新的渲染。
但是您的情况很特殊,您需要在DOM更新之前执行给定的更新。
为此,React有一个名为useLayoutEffect
的特殊钩子,它将在浏览器的绘画过程之前运行。对于您来说,这只是一个完美的用例
不再闪烁。
基于类的组件,因为componentDidUpdate
的行为要在更新之后运行,我怕getSnapshotBeforeUpdate
在这里无法为您提供帮助。如果您收到open
作为道具,可以看看getDerivedStateFromProps
。
话虽如此。好吧...难道您不只是将初始不透明度定义为0
并在动画之后添加className
来保持opacity: 1
吗?