反应-动画化单个组件的安装和卸载

发布于 2021-01-31 22:55:41

这个简单的事情应该很容易完成,但是我要把它弄复杂。

我要做的就是动画化React组件的安装和卸载。到目前为止,这是我尝试过的方法,以及每种解决方案都不起作用的原因:

  1. ReactCSSTransitionGroup -我根本不使用CSS类,因为它全都是JS样式,所以这行不通。
  2. ReactTransitionGroup-这个较低层的API很棒,但是它要求您在动画制作完成后使用回调,因此仅使用CSS过渡在此处无效。总会有动画库,这引出下一点:
  3. GreenSock-许可证对于IMO的商业用途过于严格。
  4. React Motion-这看起来很棒,但是TransitionMotion对于我需要的东西却非常混乱和过于复杂。
  5. 当然,我可以像Material UI一样做一些技巧,在其中呈现元素但保持隐藏(left: -10000px),但我宁愿不走这条路。我认为它很笨拙,并且我 希望 卸下我的组件,以便它们清理并不会弄乱DOM。

我想要一些 易于 实现的东西。在安装时,为一组样式设置动画;卸载时,为一组相同(或另一组)样式设置动画。做完了 它还必须在多个平台上都具有高性能。

我在这里撞墙了。如果我缺少某些东西,并且有一种简单的方法可以做到,请告诉我。

关注者
0
被浏览
63
1 个回答
  • 面试哥
    面试哥 2021-01-31
    为面试而生,有面试问题,就找面试哥。

    这有点冗长,但是我使用了所有本机事件和方法来实现此动画。否ReactCSSTransitionGroupReactTransitionGroup等等。

    我用过的东西

    • 反应生命周期方法
    • onTransitionEnd 事件

    如何运作

    • 根据通过的挂载道具(mounted)和默认样式(opacity: 0)来挂载元素
    • 挂载或更新后,使用componentDidMountcomponentWillReceiveProps用于进一步更新)更改样式(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>
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看