Animation in React 

liyang24 @meituan

传统方式

// JQuery
$('selector').animate({params},speed,callback);

// Velocity.js
Velocity(document.getElementById('dummy'),
    { opacity: 0.5 }, { duration: 1000 }
);
  • 先获取具体的DOM结点
  • 然后通过操作DOM的方式附加动画特效
  • 你操作的是虚拟DOM,而真正的DOM由React统一来处理
  • 等React组件每次渲染好了,再操作具体的DOM结点

第一种:操作真实DOM

React组件切入动画的两种途径

第二种:操作虚拟DOM

  • 通过props,state等数据驱动动画
  • 操作DOM的具体时机
  • 如何避免与React 组件DOM操作间的冲突

React组件生命周期 

Model Data

  • props
  • state

Lifecycle Methods

  • getInitialState(constructor)

  • componentWillMount

  • componentDidMount

  • componentWillReceiveProps

  • shouldComponentUpdate

  • componentWillUpdate

  • componentDidUpdate

  • componentWillUnmount

  • render

First Render

Props Change

State Change

Unmount

  • React + CSS Transition                        => real DOM

  • React + Data Driven (props, state)   => virtual DOM

React + CSS Transition

如何使用?

<ReactCSSTransitionGroup
    transitionName="toggle"
    component="div"
    transitionEnter={true}
    transitionEnterTimeout={800}
    transitionLeave={true}
    transitionLeaveTimeout={800}
    transitionAppear={true}
    transitionAppearTimeout={800}>
    <img key={key}
        src="http://mc.meituan.net/touch/css/download/i/ph1.png"/>
</ReactCSSTransitionGroup>

.toggle-appear {...}
.toggle-appear.toggle-appear-active {...}
.toggle-enter {...}
.toggle-enter.toggle-enter-active {...}
.toggle-leave {...}
.toggle-leave.toggle-leave-active {...}

Demo

实现逻辑 & 缺陷

ReactCSSTransitionGroup容器中,如果有设置了props key值React组件,当key值发生变动时(可以理解成React组件加入容器或从容器中移除),会经历如下六个生命周期:

  • componentWillAppear(callback)
  • componentDidAppear()
  • componentWillEnter(callback)
  • componentDidEnter()
  • componentWillLeave(callback)
  • componentDidLeave()
  1. 添加class
  2. 删除class

在一定时间间隔内,进行如下两个操作:

ReactCSSTransitionGroup容器的细节实现举例


componentWillEnter (callback) {
    const nd = React.findDOMNode(this);


    nd.classList.add(styles.enter);
    setTimeout(() => {
      nd.classList.add(styles.active)
    }, timeout);

    /*nd.addEventListener('transitionend', () => {
        if (callback) {
            callback();
        }
        nd.classList.remove(styles.enter);
        nd.classList.remove(styles.active);
    });*/

    setTimeout(() => {
        nd.classList.remove(styles.enter);
      nd.classList.add(styles.active);
    }, this.props.transitionEnterTimeout);
}

拿到真实的DOM

加class

删class

缺陷

React + Data Driven (props, state)

setInterval(() => {
    this.setState({x: this.state.x + 1})
}, 500);

最暴力的一个实例:

一个SVG 动画Demo:react.css.transition

React动画相关的开源工具

相关资源

谢谢!

Animation in React

By Ivan Lyons

Animation in React

探索一下下寫React組件時添加動畫特效時的細枝末節。

  • 4,052