在React中写一个Animation组件,为组件进入和离开加上动画/过度

Posted looyulong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在React中写一个Animation组件,为组件进入和离开加上动画/过度相关的知识,希望对你有一定的参考价值。

问题

在单页面应用中,我们经常需要给路由的切换或者元素的挂载和卸载加上过渡效果,为这么一个小功能引入第三方框架,实在有点小纠结。不如自己封装。

思路

原理

以进入时opacity: 0 --> opacity: 1 ,退出时opacity: 0 --> opacity: 1为例

元素挂载时

  1. 挂载元素dom
  2. 设置动画opacity: 0 --> opacity: 1

元素卸载时

  1. 设置动画opacity: 0 --> opacity: 1
  2. 动画结束后卸载dom

组件设计

为了使得组件简单易用、低耦合,我们期望如下方式来调用组件:

属性名 类型 描述
isShow Boolean 子元素显示或隐藏控制
name String 指定一个name,动画进入退出时的动画

App.jsx里调用组件:

通过改变isShow的值来指定是否显示

// App.jsx
// 其他代码省略
import ‘./app.css‘;

<Animation isShow=isShow name=‘demo‘>
    <div class=‘demo‘>
        demo
    </div>
</Animation>
// 通过改变isShow的值来指定是否显示

App.css里指定进入离开效果:

// 基础样式
.demo 
    width: 200px;
    height: 200px;
    background-color: red;


// 定义进出入动画
.demo-showing 
    animation: show 0.5s forwards;

.demo-fading 
    animation: fade 0.5s forwards;


// 定义动画fade与show
@keyframes show 
    from 
        opacity: 0;
    
    to 
        opacity: 1;
    


@keyframes fade 
    from 
        opacity: 1;
    
    to 
        opacity: 0;
    

根据思路写代码

// Animation.jsx
import  PureComponent  from ‘react‘;
import ‘./index.css‘;

class Animation extends PureComponent 
    constructor(props) 
        super(props);
        this.state = 
            isInnerShow: false,
            animationClass: ‘‘,
        ;
    

    componentWillReceiveProps(props) 
        const  isShow  = props;
        if (isShow) 
            // 显示
            this.show().then(() => 
                this.doShowAnimation();
            );
         else 
            // 隐藏
            this.doFadeAnimation();
        
    

    handleAnimationEnd() 
        const isFading = this.state.animationClass === this.className(‘fading‘);
        if (isFading) 
            this.hide();
        
    

    show() 
        return new Promise(resolve => 
            this.setState(
                
                    isInnerShow: true,
                ,
                () => 
                    resolve();
                
            );
        );
    

    hide() 
        this.setState(
            isInnerShow: false,
        );
    

    doShowAnimation() 
        this.setState(
            animationClass: this.className(‘showing‘),
        );
    

    doFadeAnimation() 
        this.setState(
            animationClass: this.className(‘fading‘),
        );
    

    /**
     * 获取className
     * @param string inner ‘showing‘ | ‘fading‘
     */
    className(inner) 
        const  name  = this.props;
        if (!name) throw new Error(‘animation name must be assigned‘);
        return `$name-$inner`;
    

    render() 
        let  children  = this.props;
        children = React.Children.only(children);
        const  isInnerShow, animationClass  = this.state;
        const element = 
            ...children,
            props: 
                ...children.props,
                className: `$children.props.className $animationClass`,
                onAnimationEnd: this.handleAnimationEnd.bind(this),
            ,
        ;
        return isInnerShow && element;
    


export default Animation;

Demo示例

点我直达

以上是关于在React中写一个Animation组件,为组件进入和离开加上动画/过度的主要内容,如果未能解决你的问题,请参考以下文章

1写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?

React-Router 动画 Animation

写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?

react map方法不能用是怎么回事 求大神指点迷津

react教程JSX语法组件概念生命周期介绍

Unity中的Animation组件(一)