在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示例

点我直达

原文地址:https://www.cnblogs.com/looyulong/p/11071478.html

时间: 2024-09-30 21:38:26

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

放弃antd table,基于React手写一个虚拟滚动的表格

缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反而有所上升. 客观地说,antd是开源的,UI设计得比较美观(甩出其他组件库一条街),而且是蚂蚁金服的体验技术部(一堆p7,p8,p9,基本都是大牛级的)在持续地开发维护,质量可以信任. 不过,antd虽好,但一些组件在某一些场景下,是很不适用的.例如,以表格形式无限滚动地展示大量数据(1w+)时,

[译] 如何在React中写出更优秀的代码

目录 我们先来看 Linting 利用组件模块性.复用性和组合性 propTypes 和 defaultProps 知道何时创建新组件 组件 vs 纯组件 vs 无状态函数组件 无状态函数组件 纯组件 使用 React 开发工具 使用内联条件语句 尽可能使用代码片段库 React 本质 - 学习 React 是如何工作的 快速回顾 在React中写出更好代码的9条建议:学习关于 Linting, propTypes, PureComponent 等. Rajat S · 2018 年 4 月 1

今天学习了在一般处理程序中写一个计算器

今天看了看前面的javascript以及学习的jquery,感觉刚开始学习时间就赶得比较紧,练习是做啦,基础的知识都是知道的,但是在写一些小小的程序时间还是陌生,感觉练习的还是很不够的,其实怎么说那,想好好的学习还是把他们使用到项目中练习就会学习的更快些吧,然后我又做啦一个增删改查的一般处理程序,但是还没有总结好,现在就简单的先总结一个小小的计算器使用html和ashx来实现一下其功能,如下所示: 一.html样式 <script> //@Script; </script> <

写一个高效的缓存组件(对象池)

我们在写高效服务时,许多需要缓存,一般缓存组件都需要加锁,我最近想了一个方法,感觉还不错,分享一下.直接上代码: public abstract class SimpleObjPool<T> { int _locker = 0; int _cnt = 0; T[] _ts; public SimpleObjPool(int MaxSize) { _ts = new T[MaxSize]; } protected abstract T NewObj(); public T GetObj() {

Ruby中写一个判断成绩分类的脚本

需求为:从键盘输入分数,以此来判断,0-59为不及格,打印"您没有及格,请下次努力!",60-79为及格,打印"您的成绩及格,请更加努力!",80-100为成绩良,打印"您的成绩为优秀,请再接再厉!",如果输入为0-100以外的分数,请打印"您的成绩为优秀,请再接再厉!" 如果采用ruby方式,代码比较精简,如下所示: #!/usr/bin/ruby print "请输入您的分数: " grade = ge

.net 在数据访问层中写一个DBhelper优化类

复习了在学校的时候做的WinForm端的一个学生信息管理系统,用的三层架构,看了一下里面的数据优化类 这个类是用来把对数据库的操作封装成静态方法,增删改查的时候直接调用这个类,减少项目里代码的冗余和方便以后修改. Dbhelper类代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System

如何在react中实现一个table切换?

废话不说,直接贴代码,供新手参考 export default class TabComponent extends Component { constructor(props){ super(props); this.state = { }; } render(){ return ( <TabController> <div name="one"> 第一部分 </div> <div name="two"> 第二部分

Python中写一个乒乓球类的游戏

最近开始学Python,感觉挺好玩的,既有脚本语言的灵活性,又有丰富的类库与面向对象的特点,开发起来很方便. 游戏的规则和乒乓球一样,如果妙蛙种子掉地上了就算输,你可以用蓝色的跷跷板弹它,使他不落到地面上. Game Over后可按任意键继续游戏或选择退出. 代码如下: 1 import sys, pygame 2 from random import * 3 from pygame.locals import * 4 from pygame.font import * 5 class MyPl

Vue学习—Vue写一个图片轮播组件

1.先看效果: 熟悉的图片轮播,只要是个网站,百分之90以上会有个图片轮播.我认为使用图片轮播. 第一可以给人以一种美观的感受,而不会显得网站那么呆板, 第二可以增加显示内容,同样的区域可以显示更多内容. 2.每学一个新东西 ,图片轮播都是很好的练手案例,而且,也很实用. 3.基本要求:页面加载,自动播放.鼠标悬停,停止播放.鼠标离开,继续播放 点击左右箭头切换上一张,下一张图片. 下方小圆点显示当前位第几张图片. 4.使用Vue实现,想法: 5.示例代码 结构html: <template>