如何在React中同时设置display:block和transition opacity?

时间:2017-06-06 14:02:44

标签: javascript css3 reactjs css-transitions jsx

我在JSX中定义了一个背景图层元素,它初始设置了display:none

<div id="naviBG" style={naviBGStyleClone} role="button" onClick={this.onCloseClicked} />

样式:

const naviBGStyle = {
  display: 'none',
  opacity: 0,
  transition: 'opacity 0.4s ease',
};

单击时,我希望使用css中定义的过渡平滑地消失或重新显示图层。在render()中,我检查是否应该显示或隐藏元素:

渲染()

const naviBGStyleClone = Object.assign({}, naviBGStyle);
if (this.props.status === 'closed') {
  naviBGStyleClone.display = 'none';
  naviBGStyleClone.opacity = 0;
} else {
  naviBGStyleClone.display = 'block';
  naviBGStyleClone.opacity = 1;
}

return (
    <div id="naviBG" style={naviBGStyleClone} role="button" onClick={this.onCloseClicked} />
);

现在,这种方式有效,因为元素将被显示/隐藏,但它会弹出,而不会在不透明度上设置过渡动画。

通常情况下,我会使用像requestAnimationFrame这样的东西来解决这个问题:

使用raf渲染()

const naviBGStyleClone = Object.assign({}, naviBGStyle);
if (this.props.status === 'closed') {
  naviBGStyleClone.display = 'none';
  if (typeof window !== 'undefined') {
    window.requestAnimationFrame(() => {
      naviBGStyleClone.opacity = 0;
    });
  }
} else {
  naviBGStyleClone.display = 'block';
  if (typeof window !== 'undefined') {
    window.requestAnimationFrame(() => {
      naviBGStyleClone.opacity = 1;
    });
  }
}

return (
    <div id="naviBG" style={naviBGStyleClone} role="button" onClick={this.onCloseClicked} />
);

但这不会起作用,因为它会导致在render()完成后修改样式。

那么,在React中执行此操作的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

由于转换不会触发通过display: none隐藏的项目,因此您可以连续两次调用setState,一次触发显示更改然后再次触发不透明度更改,并且以相反的顺序相同,使其淡出然后隐藏。

class App extends React.Component {
  state = { display: 'none', opacity: 0 }

  toggle = () => {
    if (this.state.display === 'none') {
      this.setState({ display: 'block' })
      setTimeout(() =>
        this.setState({ opacity: 1 }), 10 // something very short
      )
    }
    if (this.state.display === 'block') {
      this.setState({ opacity: 0 })
      setTimeout(() =>
        this.setState({ display: 'none' }), 300 // same as transition time
      )
    }
  }

  render() {
    return (
      <div>
        <button onClick={this.toggle}>toggle</button>        
        <div 
          style={{ 
            transition: 'opacity 0.3s ease',
            opacity: this.state.opacity,
            display: this.state.display
          }} 
        />
      </div>
    )
  }
}

Example on codepen

我还建议您查看React Motion处理更复杂的过渡,就像使用requestAnimationFrame

一样

https://github.com/chenglou/react-motion