问题

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

思路

原理

以进入时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. 201871010109-胡欢欢《面向对象程序设计(java)》第十二周学习总结

    201871010109-胡欢欢<面向对象程序设计(java)>第十二周学习总结   内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这 ...

  2. 201871010133-赵永军《面向对象程序设计(java)》第十周学习总结

    201871010133-赵永军<面向对象程序设计(java)>第十周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这 ...

  3. centos 7 服务初始化

    更新yum源及必要软件安装 yum groupinstall "Development tools" "Compatibility libraries" yum ...

  4. 获取 Docker 容器的 IP 地址

    docker inspect --format='{{.NetworkSettings.IPAddress}}' yourContainerIdOrContainerName

  5. day24_7.30 反射与元类

    一.反射 在python中,反射通常是指一个对象应该具备,可以检测修复,增加自身属性的能力. 而反射可以通过字符串对其进行操作. 其中涉及了4个函数,是四个普通 的函数: hasattr(oop,st ...

  6. win10经常无法复制粘贴

    两种方法尝试一下: 1. 在c:\windows\system32 目录下新建文件夹,命名为clip 2. 因为有道词典会监控并占用你的剪贴板,请尝试关闭有道词典的[取词]和[划词]功能,如果还不行就 ...

  7. elasticsearch 7.5.0 学习笔记

    温馨提示:电脑端看不到右侧目录的话请减小缩放比例. API操作-- 新建或删除查询索引库 新建索引库 新建index,要向服务器发送一个PUT请求,下面是使用curl命令新建了一个名为test的ind ...

  8. okhttp 发送get post 请求

    package com.qlwb.business.util; import java.util.Map; import com.alibaba.fastjson.JSON; import okhtt ...

  9. 一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构

    1.前言 本文内容讲解的内容:一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构. 项目地址:https://github.com/biaochenxuying/vu ...

  10. 聊聊Runloop

    1.什么是Runloop 在开始聊RunLoop之前,我们先来了解一下程序的执行原理.一般来说,程序是在线程中执行,一个线程一次只能执行一个任务(关于GCD,可看上篇文章介绍),执行完成后线程就会退出 ...