反应-动画化单个组件的安装和卸载 [英] React - animate mount and unmount of a single component

查看:91
本文介绍了反应-动画化单个组件的安装和卸载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Something this simple should be easily accomplished, yet I'm pulling my hair out over how complicated it is.

我要做的就是为安装和放大动画。 ;卸载React组件就可以了。这是到目前为止我一直在尝试的原因,以及每个解决方案都不起作用的原因:

All I want to do is animate the mounting & unmounting of a React component, that's it. Here's what I've tried so far and why each solution won't work:


  1. ReactCSSTransitionGroup -我根本不使用CSS类,因为它们都是JS样式,所以这行不通。

  2. ReactTransitionGroup -这个较低级别的API很棒,但是它要求您在动画完成后使用回调,因此仅使用CSS过渡在此处无效。总是有动画库,这引出了下一个问题:

  3. GreenSock-许可对于业务使用IMO而言过于严格。

  4. React Motion-这似乎很棒,但是 TransitionMotion 令我非常困惑,而且过于复杂。

  5. 我当然可以像Material一样做些诡计UI可以,其中的元素已呈现但仍处于隐藏状态( left:-10000px ),但我宁愿不走那条路线。我认为它很hacky,并且我想要卸下我的组件,以便它们清理并不会使DOM混乱。

  1. ReactCSSTransitionGroup - I'm not using CSS classes at all, it's all JS styles, so this won't work.
  2. ReactTransitionGroup - This lower level API is great, but it requires you to use a callback when the animation is complete, so just using CSS transitions won't work here. There are always animation libraries, which leads to the next point:
  3. GreenSock - The licensing is too restrictive for business use IMO.
  4. React Motion - This seems great, but TransitionMotion is extremely confusing and overly complicated for what I need.
  5. Of course I can just do trickery like Material UI does, where the elements are rendered but remain hidden (left: -10000px) but I'd rather not go that route. I consider it hacky, and I want my components to unmount so they clean up and are not cluttering up the DOM.

我想要实现简单的功能。在坐骑上,设置一组样式的动画;卸载时,为一组相同(或另一组)样式设置动画。做完了在多个平台上也必须具有高性能。

I want something that's easy to implement. On mount, animate a set of styles; on unmount, animate the same (or another) set of styles. Done. It also has to be high performance on multiple platforms.

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

I've hit a brick wall here. If I'm missing something and there's an easy way to do this, let me know.

推荐答案

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

This is a bit lengthy but I've used all the native events and methods to achieve this animation. No ReactCSSTransitionGroup, ReactTransitionGroup and etc.

我使用过的东西


  • 反应生命周期方法

  • onTransitionEnd 事件

  • React lifecycle methods
  • onTransitionEnd event

工作原理


  • 根据已通过的mount prop( mount )和默认样式( opacity:0

  • 安装或更新后,使用 componentDidMount componentWillReceiveProps 进行进一步更新)以更改样式(不透明度:1 ),并带有超时(使其异步)。

  • 在卸载期间,将道具传递给组件以识别卸载,然后再次更改样式( opacity:0 ), onTransitionEnd ,从DOM中删除该元素。

  • Mount the element based on the mount prop passed(mounted) and with default style(opacity: 0)
  • After mount or update, use componentDidMount (componentWillReceiveProps for further updates)to change the style (opacity: 1) with a timeout(to make it async).
  • During unmount, pass a prop to the component to identify unmount, change the style again(opacity: 0), onTransitionEnd, remove unmount the element from the DOM.

继续循环。

遍历代码,您会明白的。

Go through the code, you'll understand. If any clarification is needed, please leave a comment.

希望这会有所帮助。

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>

这篇关于反应-动画化单个组件的安装和卸载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆