这应该是如此简单,但我已经打破了这几天.我正在尝试动画我的页面过渡.问题是文件SUCK.我一遍又一遍地跟着他们,尝试了各种方式,但无法让它发挥作用.
我想要做的是向右或向左优雅地滑动我的页面,并淡化正在其后面优雅地卸载的页面.简单吧?我没有在我的网页上使用React Router.
我为此尝试了各种解决方案,但问题似乎在于卸载.更换页面后,现有页面可以在转换之前卸载.我正在使用react-transition-group发布我的尝试,尽管在这一点上,我会接受任何其他有效的解决方案.我不确定react-transition-group是否在实际上得到积极维护,因为还有很多其他帖子可以帮助我做出0回复.
所以在我的app容器上我想放这样的东西:
<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); transform: translate3d(100%,0); } //to this .page-right-enter-active { -webkit-transform: translate3d(0,0); transform: translate3d(0,0); } //exiting go from this .page-right-exit { opacity: 1; } //to this .page-right-exit-active { opacity: 0; }
所有这些组件都将通过Redux连接,以便他们知道何时触发了新页面以及调用了哪个方向.
有人PLEEEEASE可以帮助我吗?我真的花了几天时间在那里尝试了每个图书馆.我并没有结合反应过渡组!任何在卸载时工作的库我都会尝试.为什么这不容易?
解决方法
好.好吧,我为WAAAAY挣扎太久了.我终于抛弃了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',},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} }
app.js
<div id="app"> <PageSlider page={this.state.nextRoute} fromDir={this.state.fromDir}/> </div>