问题

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

思路

原理

以进入时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. 放弃antd table,基于React手写一个虚拟滚动的表格

    缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...

  2. 手写一个简单的starter组件

    spring-boot中有很多第三方包,都封装成starter组件,在maven中引用后,启动springBoot项目时会自动装配到spring ioc容器中. 思考: 为什么我们springBoot ...

  3. 【Filter 不登陆无法访问】web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面的功能

    在web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面,而重定向到登陆界面的功能. 项目是用springMVC+spring+hibernate实现 (和这个没有多大关系) 第一步: 首先 ...

  4. Ionic 2 中创建一个照片倾斜浏览组件

    内容简介 今天介绍一个新的UI元素,就是当我们改变设备的方向时,我们可以看到照片的不同部分,有一种身临其境的感觉,类似于360全景视图在移动设备上的应用. 倾斜照片浏览 Ionic 2 实例开发 新增 ...

  5. Tsx写一个通用的button组件

    一年又要到年底了,vue3.0都已经出来了,我们也不能一直还停留在过去的js中,是时候学习并且在项目中使用一下Ts了. 如果说jsx是基于js的话,那么tsx就是基于typescript的 废话也不多 ...

  6. AngularJS中写一个包裹HTML元素的directive

    有这样的一个场景,这里有一个表单: <form role="form">    ...</form> 我们希望在form的外层动态包裹上一层. 有可能是这样 ...

  7. 在vue中写一个跟着鼠标跑的div,div里面动态显示数据

    1.div应该放在body里面,这是我放在body中的一个div里面的div <!-- 信息查看层 --> <div class="floatDiv" :styl ...

  8. 如何在react中实现一个倒计时组件

    倒计时组件 import React, { Component } from 'react' import $ from 'jquery' import "../../css/spellTE ...

  9. 如何在 React Native 中写一个自定义模块

    https://my.oschina.net/jpushtech/blog/983230

随机推荐

  1. SDL2学习(一): 显示一张图片

    SDL是一个跨平台的多媒体库,它通过OpenGL和2D视频帧缓冲,提供了针对音频.视频.键盘.鼠标.控制杆及3D硬件的低级别的访问接口.这里使用较新的SDL2库. 1. 配置SDL开发环境 1.1 下 ...

  2. 了解html标签

    <title></title> 1.网页标题 2.当我们收藏网页时,默认标题就是网页标题 3.seo(搜索引擎优化) <h1></h1>~<h6& ...

  3. 【oracle】merge into 函数

  4. python 面试真题

    0.Python是什么? Python是一种解释型语言.但是跟C和C的衍生语言不同,Python代码在运行之前不需要编译.其他解释型语言还包括PHP和Ruby. Python是动态类型语言,指的是在声 ...

  5. 配置好运行后Error creating context 'spring.root': Could not load type from string value

    在Webconfig文件的当前项目下引用相关项目

  6. idea中使用python环境

    idea中使用python环境,需要下载相关的python sdk 可以添加选择自己的python环境

  7. Debian 9 部分快捷键失效问题

    教程 具体修复过程: 安装gnome-screensaver包,重启恢复正常.

  8. Mysql查询数据库状态及信息

    使用MySQL时,需要了解当前数据库的情况,例如当前的数据库大小.字符集.用户等等.下面总结了一些查看数据库相关信息的命令 1:查看显示所有数据库 mysql> show databases; ...

  9. Codeforces Round #545 (Div. 2) 交互 + 推公式

    https://codeforces.com/contest/1138/problem/F 题意 有一条长为t的链,一个长为c的环,定义终点为链和环相连环上的第一个点,现在有10个人在起点,你每次可以 ...

  10. 【2019.7.26 NOIP模拟赛 T1】数字查找(figure)(数学)

    推式子 我们设\(n=kp+w\),则: \[(kp+w)a^{kp+w}\equiv b(mod\ p)\] 将系数中的\(kp+w\)向\(p\)取模,指数中的\(kp+w\)根据欧拉定理向\(p ...