React 16.x折腾记 - (2) 实现路由动效过渡,并解决过程中奇奇怪怪的问题

简介: 写这个只是更好的梳理下我实现过程中遇到的奇奇怪怪的问题,因为着实浪费了我不少时间..肯定有不少也碰到过其中的问题希望对小伙伴有所帮助。


前言


写这个只是更好的梳理下我实现过程中遇到的奇奇怪怪的问题,


因为着实浪费了我不少时间..肯定有不少也碰到过其中的问题


希望对小伙伴有所帮助。


效果图


  • 我命名为spread的效果,其实就是结合放大和旋转以及透明度的特性



  • 渐隐渐现fade



基础依赖


  • styled-components@3.4.2 : 写样式的
  • react-transition-group@2.4.0 : 路由过渡的,react官方的
  • react-router-dom@4.3.1 : react自家路由
  • react@16.4.2


问题有三,亦能解决


组件堆叠问题


就是再次进入路由切换的时候,之前的元素还没有消失,而新的组件渲染了,同时出现


  • 堆叠问题,只能用脱离文档流来解决,所以用position:absolute来负责渲染区域即可
  • 注意父层需要position:relative, 不然会一直往上找相对位置,实在找不到会相对窗口


点击侧边栏,组件一直重复渲染的问题


  • 一开始想的是去子组件区域,用shouldComponentUpdate来判断URL然后阻止渲染,发现不可行
  • 因为过渡外部用的location.key是随机性的,所以组件每次都会重新渲染
  • 最终的解决方案,是改掉了侧边栏的Link组件,直接用事件绑定(history.push来跳转),完美


随机切换效果


  • 这个结合CSSTransition的特性,因为location.key是随机性的,不同值都会走一遍;
  • 那样式的绑定给个随机数就好了.随机的范围根据你添加的个数进行调整,
  • Math.random()默认返回0~1随机浮点数,这里只有两个就不用成个数了


注意: 这里的样式用的style-components来写的,感兴趣的可以自行了解下


代码实现


重复渲染的解决逻辑代码


// 路由跳转
    gotoUrl = itemurl => {
        // 拿到路由相关的信息
        const { history, location } = this.props;
        // 判断我们传入的静态路由表的路径是否和路由信息匹配
        // 不匹配则允许跳转,反之打断函数
        if (location.pathname === itemurl) {
            return;
        } else {
            history.push(itemurl);
        }
    };


组件堆叠及过渡实现(包括随机)


import React, { Component } from 'react';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import { Route, Redirect, withRouter, Switch } from 'react-router-dom';
import styled from 'styled-components';
import { observer, inject } from 'mobx-react';
import asyncComponent from 'components/asyncComponent/asyncComponent';
const RouterAnimationClass = styled.div`
    .fade-appear,
    .fade-enter {
        opacity: 0;
    }
    .fade-appear-active,
    .fade-enter-active {
        transition: opacity 0.3s linear;
        opacity: 1;
    }
    .fade-exit {
        transition: opacity 0.2s linear;
        opacity: 1;
    }
    .fade-exit-active {
        opacity: 0;
    }
    .spread-appear,
    .spread-enter {
        opacity: 0.5;
        transform: scale(0) rotate(30deg);
    }
    .spread-appear-active,
    .spread-enter-active {
        opacity: 1;
        transform: scale(1) rotate(0);
        transition: transform 0.3s ease-in-out;
    }
    .spread-exit {
        transition: transform 0.2s ease-in-out;
        transform: scale(1.2) rotate(-30deg);
    }
    .spread-exit-active {
        transform: scale(0) rotate(0);
    }
    .page-content {
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        right: 0;
        width: 100%;
    }
`;
const Monitor = asyncComponent(() => import('pages/DashBoard/Monitor'));
const Analyze = asyncComponent(() => import('pages/DashBoard/Analyze'));
import ErrorPage from 'pages/Error/Error'; // 报错页面
@inject('auth')
@withRouter
@observer
class Container extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        const { location } = this.props;
        return (
            <RouterAnimationClass>
                <TransitionGroup>
                    <CSSTransition
                        key={location.key}
                        classNames={
                            ['fade', 'spread'][parseInt(Math.random(), 10)]
                        }
                        timeout={1000}>
                        <div className="page-content">
                            <Switch location={location}>
                                <Route
                                    path="/dashboard/monitor"
                                    exact
                                    component={Monitor}
                                />
                                <Route
                                    path="/dashboard/analyze"
                                    exact
                                    component={Analyze}
                                />
                                <Redirect
                                    exact
                                    from="/"
                                    to="/dashboard/monitor"
                                />
                                <Route component={ErrorPage} />
                            </Switch>
                        </div>
                    </CSSTransition>
                </TransitionGroup>
            </RouterAnimationClass>
        );
    }
}
export default Container;
目录
相关文章
|
2月前
|
前端开发 JavaScript
React项目路由懒加载lazy、Suspense,使第一次打开项目页面变快
本文介绍了在React项目中实现路由懒加载的方法,使用React提供的`lazy`和`Suspense`来优化项目首次加载的速度。通过将路由组件改为懒加载的方式,可以显著减少初始包的大小,从而加快首次加载速度。文章还展示了如何使用`Suspense`组件包裹`Switch`来实现懒加载过程中的fallback效果,并提供了使用前后的加载时间对比,说明了懒加载对性能的提升作用。
177 2
React项目路由懒加载lazy、Suspense,使第一次打开项目页面变快
|
16天前
|
前端开发 API UED
React 路由守卫 Guarded Routes
【10月更文挑战第26天】本文介绍了 React 中的路由守卫(Guarded Routes),使用 `react-router-dom` 实现权限验证、登录验证和数据预加载等场景。通过创建 `AuthContext` 管理认证状态,实现 `PrivateRoute` 组件进行路由保护,并在 `App.js` 中使用。文章还讨论了常见问题和易错点,提供了处理异步操作的示例,帮助开发者提升应用的安全性和用户体验。
31 1
|
3月前
|
移动开发 资源调度 前端开发
介绍React路由模式
【8月更文挑战第10天】介绍React路由模式
57 12
|
19天前
|
前端开发 安全 网络安全
React——路由Route
React——路由Route
27 2
React——路由Route
|
1月前
|
资源调度 前端开发 测试技术
React Router 路由管理
【10月更文挑战第10天】本文介绍了 React Router,一个在 React 应用中管理路由的强大工具。内容涵盖基本概念、安装与使用方法、常见问题及解决方案,如路由嵌套、动态路由和路由守卫等,并提供代码示例。通过学习本文,开发者可以更高效地使用 React Router,提升应用的导航体验和安全性。
201 19
|
1月前
|
前端开发 网络架构
React 路由
10月更文挑战第11天
33 2
|
1月前
|
前端开发 JavaScript 网络架构
实现动态路由与状态管理的SPA——使用React Router与Redux
【10月更文挑战第1天】实现动态路由与状态管理的SPA——使用React Router与Redux
32 1
|
2月前
|
前端开发 Python
React技术栈-React路由插件之自定义组件标签
关于React技术栈中React路由插件自定义组件标签的教程。
54 4
React技术栈-React路由插件之自定义组件标签
|
2月前
|
移动开发 前端开发 应用服务中间件
React两种路由模式的实现原理
React两种路由模式的实现原理
83 3
|
2月前
|
前端开发 程序员 API
React技术栈-React路由插件之react-router的基本使用
这篇博客介绍了React路由插件react-router的基本使用,包括其概念、API、以及如何通过实战案例在React应用中实现SPA(单页Web应用)的路由管理。
68 9