5

我想知道是否有人可以提供一些关于如何使用 React.js 实现动画组件/页面切换的见解。

我想要实现的是一个组件/页面转换,就像http://www.semplicelabs.com/上的那个 - 一个转换不透明度和边距顶部的标题以及一个转换不透明度的内容。

当显示新组件/页面时,当前显示的组件/页面应在新组件/页面过渡之前过渡出去。到目前为止,我所拥有的LayoutComponent是将页面组件呈现为CSSTransitionGroup

import React from 'react/addons';

export default class LayoutComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { page: '' };
  },

  setPage(page) {
    this.setState({ page });
  }

  render() {
    return (
      <React.addons.CSSTransitionGroup transitionName='page'>
        {this.state.page}
      </React.addons.CSSTransitionGroup>
    );
  }
}

我也有两个页面组件,FirstPageSecondPage.

import React from 'react';

export default class FirstPage extends React.Component {
  render() {
    return (
      <div>
        <header className='header'>
          <div className='container'>
            First Header
          </div>
        </header>
        <div className='content'>
          <div className='container'>
            First Content
          </div>
        </div>
      </div>
    );
  }
}

SecondPage代码和FirstPage代码之间的唯一区别是.containerdiv 中的内容和类名。

然后我尝试做的是添加一个带有持续时间的离开过渡和一个带有持续时间和延迟.8s的进入过渡。.8s我看到的主要问题是新页面组件是在旧页面组件的离开过渡完成之前安装的。这是我当前的 CSS:

.page-enter {
  background-color: #f2f2f2;
  transition: background-color .8s linear .8s;
}

.page-enter-active {
  background-color: #f2f1f1;
}

.page-leave {
  background-color: #f2f1f1;
  transition: background-color .8s linear;
}

.page-leave-active {
  background-color: #f2f2f2;
}

.page-enter .header {
  margin-top: -80px;
  opacity: 0;
  transition: opacity .8s ease-in-out .8s;
  transition: margin-top .8s ease-in-out .8s;
}

.page-enter-active .header {
  margin-top: 0;
  opacity: 1;
}

.page-leave .header {
  margin-top: 0;
  opacity: 1;
  transition: opacity .8s ease-in-out;
  transition: margin-top .8s ease-in-out;
}

.page-leave-active .header {
  margin-top: -80px;
  opacity: 0;
}

.page-enter .content {
  opacity: 0;
  transition: opacity .8s ease-in-out .8s;
}

.page-enter-active .content {
  opacity: 1;
}

.page-leave .content {
  opacity: 1;
  transition: opacity .8s ease-in-out;
}

.page-leave-active .content {
  opacity: 0;
}

我知道我可以动画初始安装transitionAppear={true}- 但这无助于在旧组件过渡之前安装新组件的问题。

这是我几天来一直在努力解决的问题,但我找不到解决方案。

一些可以玩的代码: https ://jsfiddle.net/gonsfx/xva2g6oo/

4

2 回答 2

1

我在页面中添加了一个状态以保存一个opacity(用于动画)并将其设置为 1(初始 = 0),当组件确实以一个小的延迟安装时。所以我在每个页面上添加了两个功能。

componentDidMount() {
    setTimeout(() => {
        this.setState({
            opacity: 1
        });
    }, 20);
}

getStyle() {
    return { opacity: this.state.opacity };
}

然后我添加了一个构造函数来制作初始的东西......

constructor(props) {
    super(props);
    this.state = { opacity: 0 };
    this.getStyle = this.getStyle.bind(this);
    this.componentDidMount = this.componentDidMount.bind(this);
}

是一个演示。

组件将立即出现在页面上,所以我认为不可能制作淡出动画(至少,我没有找到解决方案)。

于 2015-07-01T12:25:14.620 回答
0

好的。在浏览了许多最新和过时的文档之后,我设法解决了这个问题。这是解决方案

基本上,react-router 只关心父容器的动画。但这意味着使用ReactTransitionGroup,我们可以挂钩到componentWillLeave现有组件中的方法,在那里我们可以让单个子级进行操作。儿童组件也可以运动ReactCSSTransitionGroup以促进appear过渡。

所以你可能不能只使用和CSSTransitionGroup,而是混合使用。CSSTransitionGroupTransitionGroup

因此,更改页面将通过钩子自动为子级设置动画,而进入页面将使用CSSTransitionGroup单个动画。

解决方案中的setTimeoutin 可能看起来像一个 hack,但这就是我现在所能做的。

于 2015-09-15T10:29:30.417 回答