反应-动画化单个组件的安装和卸载
这个简单的事情应该很容易完成,但是我要把它弄复杂。
我要做的就是动画化React组件的安装和卸载。到目前为止,这是我尝试过的方法,以及每种解决方案都不起作用的原因:
ReactCSSTransitionGroup
-我根本不使用CSS类,因为它全都是JS样式,所以这行不通。ReactTransitionGroup
-这个较低层的API很棒,但是它要求您在动画制作完成后使用回调,因此仅使用CSS过渡在此处无效。总会有动画库,这引出下一点:- GreenSock-许可证对于IMO的商业用途过于严格。
- React Motion-这看起来很棒,但是
TransitionMotion
对于我需要的东西却非常混乱和过于复杂。 - 当然,我可以像Material UI一样做一些技巧,在其中呈现元素但保持隐藏(
left: -10000px
),但我宁愿不走这条路。我认为它很笨拙,并且我 希望 卸下我的组件,以便它们清理并不会弄乱DOM。
我想要一些 易于 实现的东西。在安装时,为一组样式设置动画;卸载时,为一组相同(或另一组)样式设置动画。做完了 它还必须在多个平台上都具有高性能。
我在这里撞墙了。如果我缺少某些东西,并且有一种简单的方法可以做到,请告诉我。
-
这有点冗长,但是我使用了所有本机事件和方法来实现此动画。否
ReactCSSTransitionGroup
,ReactTransitionGroup
等等。我用过的东西
- 反应生命周期方法
onTransitionEnd
事件
如何运作
- 根据通过的挂载道具(
mounted
)和默认样式(opacity: 0
)来挂载元素 - 挂载或更新后,使用
componentDidMount
(componentWillReceiveProps
用于进一步更新)更改样式(opacity: 1
)并带有超时(以使其异步)。 - 在卸载过程中,将prop传递给组件以识别卸载,再次更改样式(
opacity: 0
),onTransitionEnd
然后从DOM中移除元素。
继续循环。
查看代码,您会明白的。如果需要任何澄清,请发表评论。
希望这可以帮助。
class App extends React.Component{ constructor(props) { super(props) this.transitionEnd = this.transitionEnd.bind(this) this.mountStyle = this.mountStyle.bind(this) this.unMountStyle = this.unMountStyle.bind(this) this.state ={ //base css show: true, style :{ fontSize: 60, opacity: 0, transition: 'all 2s ease', } } } componentWillReceiveProps(newProps) { // check for the mounted props if(!newProps.mounted) return this.unMountStyle() // call outro animation when mounted prop is false this.setState({ // remount the node when the mounted prop is true show: true }) setTimeout(this.mountStyle, 10) // call the into animation } unMountStyle() { // css for unmount animation this.setState({ style: { fontSize: 60, opacity: 0, transition: 'all 1s ease', } }) } mountStyle() { // css for mount animation this.setState({ style: { fontSize: 60, opacity: 1, transition: 'all 1s ease', } }) } componentDidMount(){ setTimeout(this.mountStyle, 10) // call the into animation } transitionEnd(){ if(!this.props.mounted){ // remove the node on transition end when the mounted prop is false this.setState({ show: false }) } } render() { return this.state.show && <h1 style={this.state.style} onTransitionEnd={this.transitionEnd}>Hello</h1> } } class Parent extends React.Component{ constructor(props){ super(props) this.buttonClick = this.buttonClick.bind(this) this.state = { showChild: true, } } buttonClick(){ this.setState({ showChild: !this.state.showChild }) } render(){ return <div> <App onTransitionEnd={this.transitionEnd} mounted={this.state.showChild}/> <button onClick={this.buttonClick}>{this.state.showChild ? 'Unmount': 'Mount'}</button> </div> } } ReactDOM.render(<Parent />, document.getElementById('app')) <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-with-addons.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div>