反应动画同步

React animation synchronization

我有以下 React 组件:

var Hello = React.createClass({

    getInitialState: function() {
        return {
            visibility: 'visible'
        };
    },

    toggleState: function() {
        if (this.state.visibility === 'visible') {
            this.setState({visibility: 'hidden'});
        } else {
            this.setState({visibility: 'visible'});
        }
    },

    componentDidMount: function () {
        var self = this;
        setInterval(function() {
            self.toggleState();
        }, 5000);
    },

    render: function() {
        return <div className={"animated " + (this.state.visibility === 'visible' ? 'fadeIn' : 'fadeOut')}>{this.state.visibility}</div>;
    }

});

参见 fiddle here

基本上,我通过 state 属性 visibility.

使用 animate.css 控制显示的字符串和组件可见性

副作用是,当组件淡出时,它显示 "hidden" 然后开始隐藏。我想早点开始动画,只有在完成后才更改字符串,这样 "hidden" 就不会真正显示出来。

实现这种同步的最佳方法是什么?

我的解决方案是使用 ref 来 "manually" 将组件的文本和可见性与 setTimeout:

同步
render: function() {
  return <div ref="hello">visible</div>;
}

componentWillUpdate: function(next_props, next_state) {
  var self = this;
  if (next_state.visibility === 'visible') {
    this.refs.hello.className = 'animated fadeIn';
    this.refs.hello.innerHTML = 'visible';
  } else {
    this.refs.hello.className = 'animated fadeOut';
    setTimeout(function(){
      self.refs.hello.innerHTML = 'hidden';
    }, 1000);
  }
},

Fiddle here.

隐藏动画完成后更改状态的最佳方法是侦听 animationend 事件。由于仅当您的组件具有 hidden 可见性状态时才需要更改文本状态,因此您应该在隐藏动画完成后立即更改它,并在开始动画时改回 visible

text 扩展 state:

getInitialState: function() {
  return {
    visibility: 'visible',
    text: 'visible'
  }
}

所以你应该在componentDidMount中添加监听器:

componentDidMount: function() {
  this.refs.animated.addEventListener('animationend', this.toggleText); // add ref="animated" element
  // rest code
}

添加 toggleText 方法以在动画结束时更改文本状态:

toggleText: function() {
  if (this.state.visibility === 'hidden') { // change only on hidden state
    this.setState({
      text: 'hidden'
    });
  }

}

并在动画开始时将文本更改为 visible,因此:

toggleState: function() {
  if (this.state.visibility === 'visible') {
    this.setState({visibility: 'hidden'}); // text should not be changed immediately
  } else {
    this.setState({visibility: 'visible', text: 'visible'}); // change the text on show animation start
  }

}

至此完成fiddle