簡體   English   中英

Next.js 頁面過渡

[英]Next.js page transition

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

組件/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,但對該包的使用率低感到不舒服,我只是想要一個更簡單的解決方案。

我最近也在研究如何實現這一點。 查看下一頁過渡的簡要文檔,實現簡單的淡入/淡出頁面過渡就像在 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 鈎子,您可以使用它以類似的方式定位退出節點。

我對這項工作的嘗試,但它進行了渲染,您會在狀態再次更新之前看到頁面閃爍,告訴它開始淡出然后淡入。我需要在渲染之前更新狀態。

這個問題可以通過將display: none默認放在你的組件上來解決,然后一旦頁面完全呈現,顯示它並在需要時應用動畫

使用key ....

只有當route發生變化時, Key才會觸發頁面更改轉換。

你可以這樣做:

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

    return (
      <Container>
        <PageTransition>
          <Component {...pageProps} key={router.route} />
        </PageTransition>
      </Container>
    );
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM