前言
寫這個只是更好的梳理下我實現過程中遇到的奇奇怪怪的問題..
因為著實浪費了我不少時間..肯定有不少也碰到過其中的問題
希望對小夥伴有所幫助
效果圖
- 我命名為
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
是隨機性的,不同值都會走一遍; - 那樣式的繫結給個隨機數就好了.隨機的範圍根據你新增的個數進行調整
- 這個結合
注意: 這裡的樣式用的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() * 2, 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;
複製程式碼
僅供參考,部分你們沒用到的可以移除掉
總結
很多坑你在其中的時候,谷歌,官方文件,github issue都翻遍了也沒鳥用;
還有一些QQ群的群友給我一些不意思的思路,終於給摸索出來了;
發現寫法也就那樣..但是那消磨在裡面的,是我的青春~~~ 生命不息,折騰不止!
有不對之處請留言,會及時修正,謝謝閱讀