react按需加载和ReactTransitionGroup页面过渡共同使用产生的问题

3,413 阅读3分钟

由vue过渡到react,在react中想给页面或组件添加类似于vue里面的transition,并附带out-in的模式的时候(即当前元素先进行过渡,完成之后新元素过渡进入),发现以下几个问题并逐一解决:

使用版本

项目使用create-react-app创建

{
react:"16.9.1",
react-router-dom:"^5.0.1",
react-transition-group: "^4.3.0"
}

Q1:如何实现React按需加载?

参考官方文档:react-1251415695.cos-website.ap-chengdu.myqcloud.com/docs/code-s…

const message = lazy(() => import('./Message/messageCenter'))
const analysis = lazy(() => import('./DataAnalysis/dataAnalysis'))

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

React.lazy 和 Suspense 技术还不支持服务端渲染。

Q2:如何实现页面过渡效果?

网上的教程大多数为老版本,现在官方提供的是叫react-transition-group,但是官网写得不怎么友好,阅读起来有点困难

官网为:reactcommunity.org/react-trans…

主要分为以下四个部分:

  • Transition:给单个组件添加过渡
  • CSSTransition:控制过渡动画效果的模块,需要配合使用
  • SwitchTransition(新增):参考vue的out-in的模式实现的,控制组件进入和离开动画的加载顺序,避免只能同时加载
  • TransitionGroup:给列表组件添加过渡

具体使用及配合React-Router使用

参考进行使用:segmentfault.com/a/119000001… ,此处不再赘述

看完上述文章实现vue-router过渡,再配合上按需加载,你就会得到:

import React, {Component, Suspense, lazy } from 'react';
import { Route,Switch,RouteComponentProps } from "react-router-dom";

import './allStyle.css'

import { CSSTransition, TransitionGroup } from 'react-transition-group';

const message = lazy(() => import('./Message/messageCenter'))
const analysis = lazy(() => import('./DataAnalysis/dataAnalysis'))

class AppRouter extends Component<RouteComponentProps>{
  render(){
   const {history,location} = this.props
    return(
        <Suspense fallback={<div>Loading...</div>}>
        <TransitionGroup>
          <CSSTransition
          classNames={'fade'}
          key={location.pathname}
          timeout={300}>
              <Switch location={location}>
                  <Route path="/messagecenter"  component={message} />
                  <Route path="/analysis"  component={analysis} />
                  <Route component={defaultError} />
              </Switch>
          </CSSTransition>
        </TransitionGroup>
        </Suspense>
        )
  }
}

export default AppRouter;

注意: 1. 记得留意上述组件的层次顺序,不能出错,Suspense->TransitionGroup->CSSTransition->Switch。 2. switch 的location记得获取到路由的location

Q3:按需加载和过渡一起使用产生了哪些问题?

1.react-router官网推荐使用的按需加载实现是loadable,测试后发现会出现白屏、无法跳转的情况,所以此处决定修改按需加载方案为React.lazy。

有理有据:reacttraining.com/react-route…

2.将按需加载的实现改为react自带的React.lazy来实现后,已经很接近了,按需加载和过渡都能同时实现(参考Q2代码)

细心的你可能已经发现了,如果没有类似于vue的out-in这样的动画模式控制的话,过渡动画是只能同时执行,然后需要移除的组件和需要加载的组件就会同时出现,右侧就会产生滚动条,很影响用户体验。

这时候我们的SwitchTransition就可以派上用场了

// 省略部分代码...
import { CSSTransition, TransitionGroup, SwitchTransition } from 'react-transition-group';


class AppRouter extends Component{
  render(){
    return(
        <Suspense fallback={<div>Loading...</div>}>
        <TransitionGroup>
            <SwitchTransition>
                <CSSTransition
                classNames={'fade'}
                key={location.pathname}
                timeout={300}>
                    <Switch location={location}>
                        <Route path="/messagecenter"  component={message} />
                        <Route path="/analysis"  component={analysis} />
                        <Route component={defaultError} />
                    </Switch>
                </CSSTransition>
            </SwitchTransition>              
        </TransitionGroup>
        </Suspense>
        )
  }
}

export default AppRouter;

问题解决啦!SwitchTransition整体实现思路都是参照vue的,默认为out-in模式,如果有其他设置参数的需求,参照官网就可以啦。

如有错误,请指正一下啦谢谢。