在组件

时间:2015-10-29 23:39:48

标签: css3 reactjs reactcsstransitiongroup

我希望在第一个组件淡出的两个组件之间制作动画,并在将下一个组件添加到DOM并淡入之前从DOM中删除。否则,新组件将添加到DOM并占用删除旧组件之前的空格。你可以在这个小提琴中看到问题:

http://jsfiddle.net/phepyezx/4

// css snippet
.switch-enter {
    opacity: 0.01;
}
.switch-enter.switch-enter-active {
    opacity: 1.0;
}
.switch-leave {
    opacity: 1.0;
}
.switch-leave.switch-leave-active {
    opacity: 0;
}

// React snippet 
<ReactCSSTransitionGroup transitionName="switch">
    <div key={key} className={className}>{this.text()}</div>
</ReactCSSTransitionGroup>

一个不可接受的解决方案(对我来说)是在转换到新组件之前用css隐藏原始组件,如下所示:

http://jsfiddle.net/phepyezx/5

// Change to css
.switch-leave {
    visibility: hidden;
    height: 0px;
    width: 0px;
    opacity: 1.0;
}

有没有办法在原件移除之前“延迟”安装新组件的反应?我对速度或其他图书馆持开放态度。

由于

3 个答案:

答案 0 :(得分:17)

另一个解决方案是使传入和传出元素占用相同的空间,例如让它们都处于绝对位置:

<ReactCSSTransitionGroup
    className="container"
    component="div"
    transitionName="switch">
...

.container {
    position: relative;
}
.container > div {
    position: absolute;
}

http://jsfiddle.net/phepyezx/7/

您可以使用transition-delay等待离开组件消失,然后再显示输入组件,例如:

.fade-enter {
  opacity: 0.01;
}
.fade-enter.fade-enter-active {
  opacity: 1;
  transition: opacity 1s;
  transition-delay: 1s;
}

.fade-leave {
  opacity: 1;
}
.fade-leave.fade-leave-active {
  opacity: 0.01;
  transition: opacity 1s;
}

答案 1 :(得分:11)

使用var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; const Off = React.createClass({ componentWillUnmount () { this.props.handleTransitionEnd(); }, render() { return ( <div className="off button">OFF</div> ) } }); const On = React.createClass({ componentWillUnmount () { this.props.handleTransitionEnd(); }, render() { return ( <div className="on button">ON</div> ) } }); var Switch = React.createClass({ getInitialState: function() { return { on: false, transitionEnd: true }; }, toggle: function(e) { this.setState({ on: !this.state.on, transitionEnd: false }); }, handleTransitionEnd() { this.setState({transitionEnd: true}); }, renderOff() { if (! this.state.on && this.state.transitionEnd) { return ( <Off key="off" handleTransitionEnd={this.handleTransitionEnd} /> ) } }, renderOn() { if (this.state.on && this.state.transitionEnd) { return ( <On key="on" handleTransitionEnd={this.handleTransitionEnd} /> ) } }, render: function() { return ( <div> <button onClick={this.toggle}>Toggle</button> <ReactCSSTransitionGroup transitionName="switch"> {this.renderOff()} {this.renderOn()} </ReactCSSTransitionGroup> </div> ); } }); React.render(<Switch/>, document.getElementById("switch")); 生命周期方法解决。

PureRenderMixin

以下是代码:

.switch-enter {
    opacity: 0.01;
}
.switch-enter.switch-enter-active {
    opacity: 1.0;
    transition: opacity 500ms ease-in;
}
.switch-leave {
    opacity: 1.0;
}
.switch-leave.switch-leave-active {
    opacity: 0;
    transition: opacity 500ms ease-out;
}

相关的css:

componentWillUnmount()

使用绝对定位和延迟代替Palette.Builder

http://jsfiddle.net/phepyezx/9/可以获得相同的有效结果

答案 2 :(得分:2)

如果您想延迟下一个组件的渲染,可以使用以下内容:

import React, { Component } from 'react';

export default class DelayedRender extends Component {

    static propTypes = {
        delay: React.PropTypes.number.isRequired,
        children: React.PropTypes.element,
        className: React.PropTypes.string
    };

    constructor(props) {
        super(props);

        this.state = {
            render: false
        };
    }

    componentDidMount() {
        setTimeout(() => {
            const delayedClassNames = this.refs.noDelayed.className;
            this.setState({
                render: true,
                classNames: delayedClassNames
            });
        }, this.props.delay);
    }

    render() {
        const { children, className } = this.props;
        return this.state.render ?
            <div className={this.state.classNames}>{children}</div> :
            <div className={className} ref="noDelayed" ></div>;
    }
}

在你的渲染方法中:

const ROUTE_TRANSITION_TIME = 500;
const views = [];

if (shouldRenderDelayedRoute) {
    views.push(
        <DelayedRender delay={ROUTE_TRANSITION_TIME} key="book">
            <A ref="book"/>
        </DelayedRender>
    );
} else {
    views.push(<B key="library"/>);
} 

<ReactCSSTransitionGroup
   transitionEnterTimeout={ROUTE_TRANSITION_TIME}
   transitionLeaveTimeout={ROUTE_TRANSITION_TIME}
   transitionName="fade-transition"
                        >
    {views}
</ReactCSSTransitionGroup>