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

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

问题

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

思路

原理

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

元素挂载时

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

元素卸载时

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

组件设计

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

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

点我直达

(0)

相关推荐

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

    在React中写一个Animation组件为组件进入和离开加上动画/过度效果 问题 在单页面应用中,我们经常需要给路由的切换或者元素的挂载和卸载加上过渡效果,为这么一个小功能引入第三方框架,实在有点小纠结.不如自己封装. 思路 原理 以进入时 opacity: 0 --> opacity: 1  ,退出时 opacity: 0 --> opacity: 1 为例 元素挂载时 1.挂载元素dom 2.设置动画 opacity: 0 --> opacity: 1 元素卸载时 1.设置动画 o

  • React手写一个手风琴组件示例

    目录 知识点 结构分析 AccordionItem子组件 Accordion容器组件 知识点 emotion语法 react语法 css语法 typescript类型语法 结构分析 根据上图,我们来分析一下,一个手风琴组件应该包含一个手风琴容器组件和多个手风琴子元素组件.因此,假设我们实现好了所有的逻辑,并写出使用demo,那么代码应该如下: <Accordion defaultIndex="1" onItemClick={console.log}> <Accordi

  • 尝试自己动手用react来写一个分页组件(小结)

    本文介绍了尝试自己动手用react来写一个分页组件(小结),分享给大家,具体如下: 分页效果 在线预览 github地址 效果截图(样式可自行修改): 构建项目 create-react-app react-paging-component 分页组件 1.子组件 创建 Pagecomponent.js 文件 核心代码: 初始化值 constructor(props) { super(props) this.state = { currentPage: 1, //当前页码 groupCount:

  • 详解如何用VUE写一个多用模态框组件模版

    对于新手们来说,如何写一个可以多用的组件,还是有点难度的,组件如何重用,如何传值这些在实际使用中,是多少会存在一些障碍的,所以今天特意写一个最常用的模态框组件提供给大家,希望能帮助到您! 懒癌患者直接复制粘贴即可 Modal.vue组件 <template> <!-- 过渡动画 --> <transition name="modal-fade"> <!-- 关闭模态框事件 和 控制模态框是否显示 --> <div class=&qu

  • React中的生命周期和子组件

    目录 组件生命周期 创建创建期 获取虚拟DOM 子组件 组件生命周期 为了说明组件的创建,存在,销毁的过程,react提供了组件的生命周期,共分三大周期: 创建期:说明组件的创建的过程,相当于人的少年 存在期:说明组件的存在的过程,相当于人的中年 销毁期:说明组件的销毁的过程,相当于人的老年 创建创建期 创建期共分五个阶段: ES5开发中,对应五个方法:getDefaultProps,getInitialsate, ​​componentWillMount​​, ​​render​​, ​​co

  • 手把手教你写一个uniapp通用页面组件

    目录 前言 需求 开发 初始化页面数据 实现状态栏与底部配置 页面使用 总结 前言 做移动端项目时为了兼容各种手机型号的界面,最好有一个统一的页面组件对样式做统一处理,例如:判断是否显示状态栏,是否显示头部导航,是否空出底部区域等等,本篇会带大家从零到一开发一个 uniapp 的通用页面组件 需求 本次开发的页面,组件,需要完成以下功能 可配置控制是否显示原生导航,显示状态栏,并且也可以控制状态栏颜色 可配置控制是否留出底部固定区域 开发 初始化页面数据 编写页面组件类,获取系统配置,初始化样式

  • React中映射一个嵌套数组实现demo

    目录 正文 平面+地图 使用嵌套地图 正文 嵌套数组本质上是一个数组的数组,你可以把它们想象成一个表格,或者一个二维网格.为了映射一个嵌套数组,你可以使用平面和映射数组函数的组合,或者使用映射中的映射. 你可能想使用哪种方法取决于你的情况,所以我将用一个例子来解释.如果你的数据只是一个一维数组,你可以简单地使用一个普通的地图,你可以通过这个教程查看. 平面+地图 flat函数将我们的二维数组转化为一维数组,然后我们可以简单地将其映射到上面以产生我们的组件.在这个例子中,我创建了一个简单的购物清单

  • 使用React手写一个对话框或模态框的方法示例

    打算用React写对话框已经很长一段时间,现在是时候兑现承诺了.实际上,写起来相当简单. 核心在于使用React的接口React.createPortal(element, domContainer).该接口将element渲染后的DOM节点嵌入domContainer(通常是document.body),并保证只嵌入一次. 所以,我们可以这样写一个对话框或模态框: function Dialog() { return React.createPortal( <div>Dialog conte

  • android中写一个内部类来选择文件夹中指定的图片类型实例说明

    复制代码 代码如下: /**本类是用来选择文件夹中是.jpg类型的图片*/ private class JpgFileFilter implements FilenameFilter{ @Override public boolean accept(File dir, String filename) { // TODO Auto-generated method stub return filename.endsWith(".jpg"); } }

  • Angular6 写一个简单的Select组件示例

    Select组件目录结构 /src /app /select /select.ts /select.html /select.css /options.ts /index.ts //select.ts import { Component, ContentChildren, ViewChild, Input, Output, EventEmitter, QueryList, HostListener } from '@angular/core'; import { NzOptionDirecti

随机推荐