解决这种情况的另一种方法可能是在动画完成后更改状态。它的好处是你不仅可以应用过渡,还可以应用任何你想要的动作(js动画、smil等),主要是不要忘记调用结束回调;)
这是工作示例CodePen
下面是代码示例:
const runTransition = (node, {property = 'opacity', from, to, duration = 600, post = ''}, end) => {
const dif = to - from;
const start = Date.now();
const animate = ()=>{
const step = Date.now() - start;
if (step >= duration) {
node.style[property] = to + post;
return typeof end == 'function' && end();
}
const val =from + (dif * (step/duration));
node.style[property] = val + post;
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
}
class Comp extends React.Component {
constructor(props) {
super(props);
this.state = {
isCollapsed: false
}
this.onclick = (e)=>{
this.hide(e.currentTarget,()=>{
this.setState({isCollapsed: !this.state.isCollapsed})
});
};
this.refF = (n)=>{
n && this.show(n);
};
}
render() {
if (this.state.isCollapsed){
return this.renderCollapsed();
}
return this.renderActive()
}
renderCollapsed() {
return (
<div
key='b'
style={{opacity: 0}}
ref={this.refF}
className={`b`}
onClick={this.onclick}>
<h2>I'm Collapsed</h2>
</div>
)
}
renderActive() {
return (
<div
key='a'
style={{opacity: 0}}
ref={this.refF}
className={`a`}
onClick={this.onclick}>
<h2>I'm Active</h2>
</div>
)
}
show(node, cb) {
runTransition(node, {from: 0, to: 1}, cb);
}
hide(node, cb) {
runTransition(node, {from: 1, to: 0}, cb);
}
}
ReactDOM.render(<Comp />, document.getElementById('content'));
当然,要让这种方法发挥作用,你唯一的机会是中继状态,而不是 Component 的 props,如果你必须处理它们,你总是可以在 componentWillReceiveProps 方法中设置它们。
更新
Codepen link 更新了更清晰的示例,展示了这种方法的好处。转场改为javascript动画,不依赖transitionend事件。