1

我正在使用_app.jsNext.js 的新文件来尝试创建页面转换,例如淡入淡出或幻灯片,但我无法理解它。我正在使用样式化组件来应用样式。我的结构目前看起来像这样:

_app.js

import App, { Container } from 'next/app';
import React from 'react';
import PageTransition from '../components/PageTransition';

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    return { pageProps };
  }

  render() {
    const { Component, pageProps } = this.props;

    return (
      <Container>
        <PageTransition>
          <Component {...pageProps} />
        </PageTransition>
      </Container>
    );
  }
}

export default MyApp;

组件/PageTransition/index.jsx

import { Transition } from 'react-transition-group';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Root from './index.style';

class PageTransition extends Component {
  state = {
    active: true,
  }

  componentDidUpdate() {
    // Check if children are different to previous children
    // If true, set this.state.active to false
    // After 1000ms transition, set to true again
  }

  render() {
    const { children } = this.props;
    const { active } = this.state;

    return (
      <Transition in timeout={1000}>
        <Root id="root" active={active}>
          {children}
        </Root>
      </Transition>
    );
  }
}

export default PageTransition;

组件/PageTransition/index.style.js

import styled from 'styled-components';

const Root = styled.div`
  opacity: ${p => (p.active ? 1 : 0)};
  transition: opacity 1000ms;
`;

export default Root;

这是一个正确的方法吗?如果是这样,我认为 componentDidUpdate 还不足以赶上页面更改。我对这项工作的尝试,但它进行了渲染,并且在状态再次更新之前您会看到页面的闪烁,以告诉它开始淡出然后淡入。我需要在渲染之前更新状态。

有没有办法用 React Transition Group 来处理这个问题?我确实查看了next-page-transitions但对包的使用率低感到不舒服,我只是想要一个更简单的解决方案。

4

3 回答 3

3

我最近也在研究如何实现这一点。浏览 next-page-transitions 的简要文档,实现一个简单的淡入/淡出页面转换就像在 App 组件渲染方法中使用它一样简单:

render() {
    const { Component, pageProps } = this.props
    return (
      <Container>
        <PageTransition timeout={300} classNames="page-transition">
          <Component {...pageProps} />
        </PageTransition>
        <style jsx global>{`
          .page-transition-enter {
            opacity: 0;
          }
          .page-transition-enter-active {
            opacity: 1;
            transition: opacity 300ms;
          }
          .page-transition-exit {
            opacity: 1;
          }
          .page-transition-exit-active {
            opacity: 0;
            transition: opacity 300ms;
          }
        `}</style>
      </Container>
    )
  }

但是,我看到您正在尝试使用 react-transition-group。如果您希望实现更复杂的动画,这就是您想要使用的库。

这是我使用 react-transition-group 进行的快速测试的 App 组件渲染方法的示例:

   render() {
        const { Component, pageProps } = this.props;
        return (
          <Container>
            <div ref={x => (this.comp = x)}>
              <TransitionGroup>
                <Transition
                  in={this.props.in}
                  key={this.props.router.route}
                  timeout={{
                    enter: 2000,
                    exit: 2000
                  }}
                  mountOnEnter={false}
                  unmountOnExit={true}
                  onEnter={this.enterTransition}
                >
                  <Component {...pageProps} />
                </Transition>
              </TransitionGroup>
            </div>
          </Container>
        );
      }

注意:我正在使用 GSAP 制作动画,在我做的这个测试中,我需要在初始安装时引用组件的内容。如果您不需要这个,那么您可以摆脱那个 div,然后确保为 onEnter 提供一个将在每个页面导航时调用的函数。

enterTransition = node => {
    TweenMax.fromTo(node, 0, { x: 0, opacity: 0 }, {x: 200, opacity: 1});
}

该节点将是下一个要挂载的组件。还有一个 onExit 钩子,您可以使用它以类似的方式定位退出节点。

于 2018-09-19T02:33:11.650 回答
0

我对这项工作的尝试,但它进行了渲染,并且在状态再次更新之前您会看到页面的闪烁,以告诉它开始淡出然后淡入。我需要在渲染之前更新状态。

这个问题可以display: none通过默认放置你的组件来解决,然后在页面完全呈现后,显示它并在需要时应用动画

于 2018-09-16T16:49:07.160 回答
0

使用key....

Key只有在更改时才会触发页面更改转换route

你可以这样做:

render() {
    const { Component, pageProps, router } = this.props;

    return (
      <Container>
        <PageTransition>
          <Component {...pageProps} key={router.route} />
        </PageTransition>
      </Container>
    );
  }
于 2021-03-07T11:09:39.050 回答