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


Posted in Javascript onJune 24, 2019

问题

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

思路

原理

以进入时 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组件为组件进入和离开加上动画/过度效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
lib.utf.js
Aug 21 Javascript
js实现的tab标签切换效果代码分享
Aug 25 Javascript
javascript实现随机显示星星特效
Jan 28 Javascript
探究JavaScript中的五种事件处理程序方式
Dec 07 Javascript
浅谈JavaScript异步编程
Jan 20 Javascript
浅谈js中function的参数默认值
Feb 20 Javascript
webpack打包js文件及部署的实现方法
Dec 18 Javascript
浅析vue深复制
Jan 29 Javascript
Vue组件和Route的生命周期实例详解
Feb 10 Javascript
vue中如何去掉空格的方法实现
Nov 09 Javascript
vue 实现单选框设置默认选中值
Nov 07 Javascript
js中addEventListener()与removeEventListener()用法案例分析
Mar 02 Javascript
node中实现删除目录的几种方法
Jun 24 #Javascript
什么时候不能在 Node.js 中使用 Lock Files
Jun 24 #Javascript
vue-cli脚手架引入弹出层layer插件的几种方法
Jun 24 #Javascript
浅谈一个webpack构建速度优化误区
Jun 24 #Javascript
vue项目中运用webpack动态配置打包多种环境域名的方法
Jun 24 #Javascript
Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条
Jun 24 #Javascript
JavaScript学习教程之cookie与webstorage
Jun 23 #Javascript
You might like
初学者入门:细述PHP4的核心Zend
2006/09/05 PHP
3.从实例开始
2006/10/09 PHP
php求正负数数组中连续元素最大值示例
2014/04/11 PHP
phpmyadmin配置文件现在需要绝密的短密码(blowfish_secret)的2种解决方法
2014/05/07 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(七)
2014/06/23 PHP
php页面函数设置超时限制的方法
2014/12/01 PHP
Yii框架在页面输出执行sql语句以方便调试的实现方法
2014/12/24 PHP
PHP使用递归生成文章树
2015/04/21 PHP
PHP7.0连接DB操作实例分析【基于mysqli】
2019/09/26 PHP
js获取提交的字符串的字节数
2009/02/09 Javascript
JavaScript 封装Ajax传递的数据代码
2009/06/05 Javascript
js调用activeX获取u盘序列号的代码
2011/11/21 Javascript
浅谈Javascript事件模拟
2012/06/27 Javascript
提示$ is not defined错误分析及解决
2013/04/09 Javascript
jQuery中:text选择器用法实例
2015/01/03 Javascript
js判断输入字符串是否为空、空格、null的方法总结
2016/06/14 Javascript
微信小程序 form组件详解及简单实例
2017/01/10 Javascript
jq给页面添加覆盖层遮罩的实例
2017/02/16 Javascript
微信小程序监听用户登录事件的实现方法
2019/11/11 Javascript
解决iView Table组件宽度只变大不变小的问题
2020/11/13 Javascript
详解vue 组件注册
2020/11/20 Vue.js
[01:04]DOTA2上海特锦赛现场采访 FreeAgain遭众解说围攻
2016/03/25 DOTA
Python实现多线程下载文件的代码实例
2014/06/01 Python
Python中字符串的处理技巧分享
2016/09/17 Python
Mac中升级Python2.7到Python3.5步骤详解
2017/04/27 Python
python最长回文串算法
2018/06/04 Python
漂亮的Django Markdown富文本app插件的实现
2019/01/02 Python
python3获取当前目录的实现方法
2019/07/29 Python
vue常用指令代码实例总结
2020/03/16 Python
Python制作数据预测集成工具(值得收藏)
2020/08/21 Python
Python析构函数__del__定义原理解析
2020/11/20 Python
用css3实现转换过渡和动画效果
2020/03/13 HTML / CSS
家乐福巴西网上超市:Carrefour巴西
2016/10/31 全球购物
机械工程师的岗位职责
2013/11/17 职场文书
文明演讲稿范文
2014/05/12 职场文书
画展观后感
2015/06/17 职场文书