【问题标题】:page transitions without React-Router没有 React-Router 的页面转换
【发布时间】:2018-12-29 18:46:39
【问题描述】:

这应该很简单,但我已经为此烦恼了好几天。我正在尝试为我的页面转换设置动画。问题是文档很烂。我一遍又一遍地跟踪他们并尝试了各种方式,但无法让它发挥作用。

我想要做的是优雅地向右或向左滑动我的页面,然后将正在卸载的页面淡出。简单吧?我的页面没有使用 React Router。

我为此尝试了多种解决方案,但问题似乎在于卸载。当页面被替换时,现有页面在它可以转换出来之前被卸载。我正在使用 react-transition-group 发布我的尝试,但在这一点上,我会接受任何其他有效的解决方案。我不确定 react-transition-group 实际上是否得到积极维护,因为还有许多其他帖子寻求帮助,但只有 0 个回复。

所以我想在我的应用容器上放这样的东西:

<App>
  <PageSlider>
     <Page key={uniqueId} />  <==this will be "swapped" through (Redux) props
  </PageSlider>

因此,根据我的阅读,我必须为此使用一个 TransitionGroup 容器作为我的 PageSlider,以便它管理我的页面的进入和退出。所以这里是:

 class PageSlider extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <TransitionGroup 
         component="div"
         id="page-slider"
         childFactory={child => React.cloneElement(child,
           {classNames: `page-${this.props.fromDir}`, timeout: 500}
         )}
      >
        {this.props.children}
      </TransitionGroup>

    );
  }
}

我还读到我需要做一个“子工厂”来启用现有的东西。我在文档中绝对找不到这样的例子。由于页面将来自不同的方向,我将传递给它我想要滑动页面的方向,这将告诉页面它得到什么类。

现在,至于页面本身,我已经将它包装在一个 CSSTransition 中,就像这样。文档中没有很好的例子说明这一切是如何传递的,所以我真的很困惑在这里做什么:

 class Page extends Component {
  constructor(props) {
    super(props);
  }

  render() {
   return (
    <CSSTransition>                   <==????????
      {this.props.children}           Do props get passed down?
    </CSSTransition>                  Which ones? 
 );                                   Does "in" get taken care of?
  }
}

为了完成,样式将在 CSS 中应用,如下所示:

.page {
  display: flex; 
  flex-direction: column; 
  height: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  -webkit-transition: all 500ms ease-in-out;
  transition: all 500ms ;
}

//go from this
.page-right-enter {
  -webkit-transform: translate3d(100%, 0, 0);
  transform: translate3d(100%, 0, 0);
}

//to this
.page-right-enter-active {
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
}

 //exiting go from this
    .page-right-exit {
      opacity: 1;
    }
   //to this
    .page-right-exit-active {
      opacity: 0;
    }

所有这些组件都将通过 Redux 连接,因此它们知道何时触发了新页面以及调用了哪个方向。

有人可以帮我解决这个问题吗?我确实花了几天时间尝试了那里的每个图书馆。我不喜欢反应过渡组!我会尝试在卸载上工作的任何库。为什么这不容易?

【问题讨论】:

    标签: css animation react-transition-group


    【解决方案1】:

    好的。好吧,我为此挣扎了太久了。我终于抛弃了 react-transition-group,转而使用纯 CSS。这是我的解决方案。

    PageSlider.js

    import React, { Component } from 'react';
    import PropTypes from 'prop-types';
    
    require('./transitions.scss');
    
    const BlankPage = (props) => <div className="placeholder"></div>;
    
    class PageSlider extends Component {
      constructor(props) {
        super(props);
        this.state = {
           nextRoute: props.page,
           pages: {
            A: {key: 'A', component: BlankPage, className: 'placeholder'},
            B: {key: 'B', component: BlankPage, className: 'placeholder'},
           },
           currentPage: 'A'
        };
      }
    
      componentDidMount() {
        //start initial animation of incoming
        let B = {key: 'b', component: this.state.nextRoute, className: 'slideFromRight'}; //new one
        let A = Object.assign({}, this.state.pages.A, {className: 'slideOutLeft'}); //exiting
        this.setState({pages: {A: A, B: B}, currentPage: 'B'});    
      }
    
      componentWillReceiveProps(nextProps) {
        if (nextProps.page != this.state.nextRoute) {
          this.transition(nextProps.page, nextProps.fromDir);
        }
      }
    
      transition = (Page, fromDir) => {
        if (this.state.nextRoute != Page) {
           let leavingClass, enteringClass;
           let pages = Object.assign({}, this.state.pages);
           const current = this.state.currentPage; 
           const next = (current == 'A' ? 'B' : 'A');
           if (fromDir == "right") {
             enteringClass = 'slideFromRight';
             leavingClass = 'slideOutLeft';
           } else {
             enteringClass = 'slideFromLeft';
             leavingClass = 'slideOutRight';
           }
           pages[next] = {key: 'unique', component: Page, className: enteringClass};
           pages[current].className = leavingClass;
           this.setState({pages: pages, nextRoute: Page, currentPage: next});  
        }
      }
    
    
      render() {
        return (
          <div id="container" style={{
            position: 'relative', 
            minHeight: '100vh',
            overflow: 'hidden'
          }}>
            {React.createElement('div', {key: 'A', className: this.state.pages.A.className}, <this.state.pages.A.component />)}
            {React.createElement('div', {key: 'B', className: this.state.pages.B.className} , <this.state.pages.B.component />)}
           </div>
      );
      }
    
    }
    
    
    PageSlider.propTypes = {
      page: PropTypes.func.isRequired,
      fromDir: PropTypes.string.isRequired
    };
    
    export default PageSlider;
    

    transition.scss

    .placeholder {
        position: absolute;
        left: 0;
        width: 100vw;
        height: 100vh;
        background: transparent;
        -webkit-animation: slideoutleft 0.5s forwards;
        -webkit-animation-delay: 10;
        animation: slideoutleft 0.5s forwards;
        animation-delay: 10;
    }
    
    
    
    .slideFromLeft {
        position: absolute;
        left: -100vw;
        width: 100vw;
        height: 100vh;
        -webkit-animation: slidein 0.5s forwards;
        -webkit-animation-delay: 10;
        animation: slidein 0.5s forwards;
        animation-delay: 10;
    }
    
    
    .slideFromRight {
        position: absolute;
        left: 100vw;
        width: 100vw;
        height: 100vh;
        -webkit-animation: slidein 0.5s forwards;
        -webkit-animation-delay: 10;
        animation: slidein 0.5s forwards;
        animation-delay: 10;;
    }
    
    .slideOutLeft {
        position: absolute;
        left: 0;
        width: 100vw;
        height: 100vh;
        -webkit-animation: slideoutleft 0.5s forwards;
        -webkit-animation-delay: 10;
        animation: slideoutleft 0.5s forwards;
        animation-delay: 10;
    }
    
    .slideOutRight {
        position: absolute;
        left: 0;
        width: 100vw;
        height: 100vh;
        -webkit-animation: slideoutright 0.5s forwards;
        -webkit-animation-delay: 10;
        animation: slideoutright 0.5s forwards;
        animation-delay: 10;
    }
    
    @-webkit-keyframes slidein {
        100% { left: 0; }
    }
    
    @keyframes slidein {
        100% { left: 0; }
    }
    
    @-webkit-keyframes slideoutleft {
        100% { left: -100vw; opacity: 0 }
    }
    
    @keyframes slideoutleft {
        100% { left: -100vw; opacity: 0}
    }
    @-webkit-keyframes slideoutright {
        100% { left: 100vw; opacity: 0}
    }
    
    @keyframes slideoutright {
        100% { left: 100vw; opacity: 0}
    }
    

    传入下一个组件,也就是我的 react Page 组件,调用方式如下:

    app.js

     <div id="app">
          <PageSlider page={this.state.nextRoute} fromDir={this.state.fromDir}/>
       </div>
    

    【讨论】:

      猜你喜欢
      • 2019-04-17
      • 2021-10-01
      • 2021-03-15
      • 2021-01-29
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 2019-02-26
      相关资源
      最近更新 更多