【问题标题】:Next.js page transitionNext.js 页面过渡
【发布时间】:2019-02-20 06:32:03
【问题描述】:

我正在使用 Next.js 的新 _app.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;

components/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;

components/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 过渡组来处理这个问题?我确实看过next-page-transitions,但对这个包的使用率很低感到不舒服,我只是想要一个更简单的解决方案。

【问题讨论】:

  • 您想在什么时候触发转换?当用户更改页面时?

标签: javascript reactjs styled-components next.js react-transition-group


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我最近也在研究如何做到这一点。翻阅关于 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 钩子,您可以使用它以类似的方式定位退出节点。

    【讨论】:

      【解决方案3】:

      使用key....

      Key 将仅在 route 发生更改时触发页面更改转换。

      你可以这样做:

      render() {
          const { Component, pageProps, router } = this.props;
      
          return (
            <Container>
              <PageTransition>
                <Component {...pageProps} key={router.route} />
              </PageTransition>
            </Container>
          );
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-08-19
        • 2012-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-22
        相关资源
        最近更新 更多