使用 React.js 的 slideUp() 和 slideDown() 动画

IT技术 javascript jquery reactjs
2021-03-23 11:56:28

我创建了一个由 slideUp() 和 slideDown() 动画组成的react组件。我已经使用 jQuery 上滑和下滑方法实现了。

我必须使用react动画来实现这个功能。

我阅读了ReactTransitionGroupReactCSSTransitionGroup解释的方式告诉我,我们可以在DomNode挂载到组件或卸载时执行此功能(如果我错了,请纠正我)。

我的问题是 --> 如何在不使用 jQuery 的情况下以react方式执行 slideup() 和 slidedown()。

请参阅此 jsFiddle 以获取https://jsfiddle.net/guc3yrm1/

PS - > 请解释一下为什么这个react动画部分与 jQuery 相比似乎有点困难(我是一个 jQuery 人)

var Hello = React.createClass({
    getInitialState: function() {
        return {
            slide: false,
        }
    },
    slide: function() {
        if (this.state.slide) {
            $(this.refs.slide).slideDown();
            this.setState({
                slide: false
            });
        } else {
            $(this.refs.slide).slideUp();
            this.setState({
                slide: true
            });
        }
    },
    render: function() {
        return ( 
            <div>
                <input type = "button" value = "clickme" onClick = {this.slide}/> 
                <br />
                <br />
                <div className = "slide" ref="slide" >< /div>
            </div>
        );
    }
});

ReactDOM.render( < Hello name = "World" / > ,
    document.getElementById('container')
);
3个回答

您可以在两个动画的 API 中实现动画。这是主要区别:

ReactTransitionGroup 是构建 ReactCSSTransitionGroup 的 API。两者的主要区别在于 ReactTransitionGroup 动画是用 Javascript 而不是 CSS 编写的,并且提供了在动画完成时调用的回调,而不是依赖于 CSS 过渡事件。

我的结论是简单任务使用 CSS 动画,复杂任务使用 Javascript。

例如,如果组件具有静态高度 - 您可以通过 CSS 实现它,如下例所示。但是如果宽度/高度是动态的,那么您可以使用 Javascript 来完成。在 Javascript 示例中,我将 Velocity 库用于动画。它的性能优于 jQuery 的动画当然你可以自己实现动画,但为什么要重新发明轮子呢?

我已经使用这两个 API 实现了 slideUp/slideDown。看看下面。

(CSS) 通过 ReactCSSTransitionGroup 实现:

const CSSTransitionGroup = React.addons.CSSTransitionGroup;
const TransitionGroup = React.addons.TransitionGroup;

class Example extends React.Component{
    constructor(props) {
        super(props);
        this.state = { visible: false };
        this.handleClick = this.handleClick.bind(this)
    }

    handleClick() {
    	this.setState({ visible: ! this.state.visible });
    }

    render() {
        return <div>
            <button onClick={this.handleClick}>{this.state.visible ? 'Slide up' : 'Slide down'}</button>
            <CSSTransitionGroup transitionName="example">
            	{ this.state.visible ? <div className='panel' /> : null }
            </CSSTransitionGroup>
        </div>
    }
}

React.render(<Example />, document.getElementById('container'));
.panel {
    width: 200px;
    height: 100px;
    background: green;
    margin-top: 10px;
}

.example-enter {
    height: 0px;
}

.example-enter.example-enter-active {
    height: 100px;
    -webkit-transition: height .3s ease;
}

.example-leave.example-leave-active {
    height: 0px;
    -webkit-transition: height .3s ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle - react向上和向下滑动动画 - CSS 转换组


(Javascript) 通过 ReactTransitionGroup 实现:

const TransitionGroup = React.addons.TransitionGroup;

class Example extends React.Component{
    constructor(props) {
        super(props);
        this.state = { visible: false };
        this.handleClick = this.handleClick.bind(this)
    }

    handleClick() {
        this.setState({ visible: ! this.state.visible });
    }

    render() {
        return <div>
            <button onClick={this.handleClick}>{this.state.visible ? 'Slide up' : 'Slide down'}</button>
                <TransitionGroup>
                    { this.state.visible ? <Accordion /> : null }
                </TransitionGroup>
            </div>
        }
    }

    class Accordion extends React.Component {
        componentWillEnter (callback) {
            const element = this.container.getDOMNode();
            Velocity(element, 'slideDown', { duration: 300 }).then(callback);
        }

        componentWillLeave (callback) {
            const element = this.container.getDOMNode();
            Velocity(element, 'slideUp', { duration: 300 }).then(callback);
        }

        setContainer(c) {
            this.container = c;
        }

        render() {
            return <div className="panel" ref={this.setContainer.bind(this)}>
                Lorem Ipsum is simply dummy text of the printing and typesetting industry.
                Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
            </div>
        }
    }

React.render(<Example />, document.getElementById('container'));
.panel {
    background: green;
    margin-top: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.4.3/velocity.min.js"></script>

<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle - react向上和向下滑动动画 - Javascript 转换组


学分:

@JordanEnev 分叉并在我的回复中提到了你 :)
2021-05-25 11:56:28
@noa-dev 你能分叉我的 JSFiddle 并通过 CSS 制作它吗?jsfiddle.net/jordan_enev/xtbxk20g
2021-05-28 11:56:28
.invisble {最大高度:0%;溢出:隐藏;} .visible{ 最大高度:100%;}
2021-05-29 11:56:28
嘿,在这种情况下,我们可以通过 Javascript - ReactTransitionGroup 来实现它。我更新了我的答案,并添加了带有 Velocity 的 Javascript 示例。
2021-06-01 11:56:28
如果面板没有固定高度怎么办?
2021-06-02 11:56:28

如果您(像我一样)来到这里是为了寻找 jQuery 的slideDown/替代品slideUp,那么react-slidedown似乎是一个易于使用的 React组件。它的 github 页面有一个演示示例代码

根据 Jordan Enev 的要求,我分叉了他的 JSFiddle。

这是一个不需要 React Css Transition Group 的解决方案。我个人是类切换的粉丝。那就是您可以随意创建 css 动画。

https://jsfiddle.net/fyuh32je/3/

(小提琴中的整个代码)

class Example extends React.Component{
    constructor(props) {
        super(props);
        this.state = { visible: 'panel' };
        this.handleClick = this.handleClick.bind(this)
    }

    handleClick() {
        this.setState({ visible: this.state.visible == 'panel'? 'panel visible' : 'panel' });
    }

    render() {
        return <div>
            <button onClick={this.handleClick}>{!this.state.visible == 'panel' ? 'Slide up' : 'Slide down'}</button>
                <div className={this.state.visible}>
                <p>This is some dynamic content!</p>
                <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
              </div>
        </div>
    }
}

React.render(<Example />, document.getElementById('container'));

我知道像这样使用可见状态变量很脏,但我在工作,没有太多时间来改变太多。请注意,我们使用可见类来切换带有动画的 div 容器。

通常来说,一般来说。动态高度容器可以使用 css 中 max-height 属性的hacky 使用动画。

嘿嘿,谢谢你的努力!实际上,一旦面板可见,您就对面板的高度值进行了硬编码。这个想法是一切都是动态的,即面板的高度与面板的内容高度相关。请查看我的 Javascript 示例。同样使用ReactCSSTransitionGroup,您可以跳过手动设置 css 类的名称。
2021-05-26 11:56:28
感谢您的解决方法!正如您已经提到的那样,这是一种有点骇人听闻的做法。您还必须手动处理 css 类名称。当然,我更喜欢 React 制作动画的方式!感谢贡献!
2021-05-29 11:56:28
@noa-dev 我怎么能在下面的链接上调整你的逻辑,保留我现有的点击事件功能?我对反应仍然是绿色的。请参阅:stackoverflow.com/questions/48692961/...
2021-06-05 11:56:28
抱歉,我忘了删除固定高度声明。我更新了我的 JS Fiddle。您可以清楚地看到容器对其内容的行为是动态的,并且在没有固定高度的情况下打开时正在动画。您可以测试并删除或添加一些文本行。
2021-06-21 11:56:28