在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 相关文章推荐
jQuery 插件 将this下的div轮番显示
Apr 09 Javascript
javascript,jquery闭包概念分析
Jun 19 Javascript
JS自调用匿名函数具体实现
Feb 11 Javascript
jquery实现倒计时代码分享
Jun 13 Javascript
jquery easyui使用心得
Jul 07 Javascript
node.js中的fs.fstatSync方法使用说明
Dec 15 Javascript
jQuery解决input超多的表单提交
Aug 10 Javascript
javascript插件开发的一些感想和心得
Feb 28 Javascript
微信小程序之GET请求的实例详解
Sep 29 Javascript
JS设计模式之状态模式概念与用法分析
Feb 05 Javascript
Vue 父子组件的数据传递、修改和更新方法
Mar 01 Javascript
详解vue 不同环境配置不同的打包命令
Apr 07 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
PHP面向对象编程快速入门
2006/12/14 PHP
默默小谈PHP&amp;MYSQL分页原理及实现
2007/01/02 PHP
php 强制下载文件实现代码
2013/10/28 PHP
PHP获取网页标题的3种实现方法代码实例
2014/04/11 PHP
laravel框架关于搜索功能的实现
2018/03/15 PHP
php+Ajax无刷新验证用户名操作实例详解
2019/03/04 PHP
javascript引导程序
2008/10/26 Javascript
向当前style sheet中插入一个新的style实现方法
2013/04/01 Javascript
JavaScript实现点击按钮后变灰避免多次重复提交
2013/07/15 Javascript
火狐下table中创建form导致两个table之间出现空白
2013/09/02 Javascript
浅谈jQuery中 wrap() wrapAll() 与 wrapInner()的差异
2014/11/12 Javascript
JavaScript中利用Array和Object实现Map的方法
2015/07/27 Javascript
JS+CSS实现下拉列表框美化效果(3款)
2015/08/15 Javascript
js实现input框文字动态变换显示效果
2015/08/19 Javascript
JS实现自动变化的导航菜单效果代码
2015/09/09 Javascript
jquery实现上传文件大小类型的验证例子(推荐)
2016/06/25 Javascript
浅谈AngularJS中ng-class的使用方法
2016/11/11 Javascript
集成vue到jquery/bootstrap项目的方法
2018/02/10 jQuery
React组件中的this的具体使用
2018/02/28 Javascript
react 实现页面代码分割、按需加载的方法
2018/04/03 Javascript
浅谈Angular 观察者模式理解
2018/11/01 Javascript
jQuery实现小火箭返回顶部特效
2020/02/03 jQuery
利用JS判断元素是否为数组的方法示例
2021/01/08 Javascript
python实现多线程采集的2个代码例子
2014/07/07 Python
Python使用Flask框架同时上传多个文件的方法
2015/03/21 Python
Python 实现子类获取父类的类成员方法
2019/01/11 Python
利用pyshp包给shapefile文件添加字段的实例
2019/12/06 Python
pytorch 常用线性函数详解
2020/01/15 Python
详解Pycharm安装及Django安装配置指南
2020/09/15 Python
美国时尚大码女装购物网站:Avenue
2019/05/24 全球购物
财务管理职业生涯规划范文
2013/12/27 职场文书
人民教师的自我评价分享
2014/02/21 职场文书
小学生期末评语大全
2014/04/21 职场文书
治庸问责心得体会
2014/09/12 职场文书
解析MySQL binlog
2021/06/11 MySQL
javascript对象3个属性特征
2021/11/17 Javascript