前言
写这个只是更好的梳理下我实现过程中遇到的奇奇怪怪的问题,
因为着实浪费了我不少时间..肯定有不少也碰到过其中的问题
希望对小伙伴有所帮助。
效果图
- 我命名为
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;