【React】路由跳转动画的实现

一、效果演示

react-transition-group转场动画: (如果无法播放可点击下载查看

二、安装

这个演示界面是通过路由实现的,谈到这个我们就不得不提到成熟的react动画库:react-transition-group 首先我们通过npm进行安装(这里假定你已经学会了使用react-router-dom,react-router,react-router-config)如果你还没有学习,那我建议你稍微进行学习后再来了解路由动画。 安装命令:

1
npm install react-transition-group --save

三、完整源码

不想看实现过程的请直接看源码实现并进行copy: index.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import React from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { Switch, Route, withRouter } from "react-router-dom";
import "./index.css";

/**
*
* @param {way} props
* @description 用于页面路由跳转 通过way指定跳转方式,指定way=refade
* 则反向
*
*/
const ANIMATION_MAP = {
PUSH: "fade",
POP: "refade",
};
function AnimationGo(props) {
const { children } = props;
// console.log(props.history.action);
// 根据动作自行判断前进和后退
/*使用React.cloneElement API对props中的classNames这一props进行修改 */
return (
<Route
render={({ location }) => (
<TransitionGroup

childFactory={(child) =>
React.cloneElement(child, {
classNames: ANIMATION_MAP[props.history.action],
})
}
>
<CSSTransition timeout={500} key={location.pathname}>
<Switch location={location}>{children}</Switch>
</CSSTransition>
</TransitionGroup>
)}
></Route>
);
}

export default withRouter(AnimationGo);

index.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* 入场动画开始 */
.fade-enter,.fade-appear {
transform: translateX(100%);
}

/*入场动画过程*/
.fade-enter-active,.fade-appear {
transform: translateX(0);
transition: transform 0.5s ease;
}

/*入场动画结束*/
/* .fade-enter-done {
transform: translateX(0);
} */

/*离场动画开始*/
.fade-exit {
transform: translateX(0);
}

/*离场动画过程*/
.fade-exit-active {
transform: translateX(-100%);
transition: transform 0.5s ease;
}

/*离场动画结束*/
.fade-exit-done {
transform: translateX(-100%);
}

/*页面第一次加载时的开始状态*/
/* .fade-appear {
transform: translateX(100%);
} */

/*页面第一次加载时的动画过程*/
/* .fade-appear-active {
transform: translateX(0%);
transition: transform 0.5s ease-in;
} */




/* 反向back */
/*入场动画开始*/
.refade-enter,.refade-appear {
transform: translateX(-100%);
}

/*入场动画过程*/
.refade-enter-active,.refade-appear-active {
transform: translateX(0%);
transition: transform 0.5s ease;
}

/*入场动画结束*/
.refade-enter-done {
transform: translateX(0%);
}

/*离场动画开始*/
.refade-exit {
transform: translateX(0%);
}

/*离场动画过程*/
.refade-exit-active {
transform: translateX(100%);
transition: transform 0.5s ease;
}

/*离场动画结束*/
.refade-exit-done {
transform: translateX(100%);
}

/*页面第一次加载时的开始状态*/
/* .refade-appear {
transform: translateX(0);
} */

/*页面第一次加载时的动画过程*/
/* .refade-appear-active {
transform: translateX(100%);
transition: transform 0.5s ease-in;
} */

挂载组件:

1
2
3
4
5
6
7
8
9
function App() {
return (
<div className="App">
<Router>
<AnimationGo>{renderRoutes(routes)}</AnimationGo>
</Router>
</div>
);
}

四、组件编写分析

创建组件编写文件夹,在这里同样不加赘述 首先导入我们所需要的一切控件,在这里,我们将通过函数式组件来构建封装这个组件

1
2
3
4
import React from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { Switch, Route, withRouter } from "react-router-dom";
import "./index.css";

导入的React不必多说,这是编写JSX必须的操作。 关于react-transition-group,它的用法看上去很类似Vue内置的Transition组件,实际上它就是以vue的transition组件为灵感进行编写的。

A transition component inspired by the vue transition modes.

在react-transition-group中,其提供了如下四个组件和一个config对象: 由于本文重点在于路由跳转动画的实现,所以它的各个详细作用,请自行查看官网文档: 我们在这里需要用到的是CSSTransiton以及TransitionGroup这两个组件,我们先来了解一下这两个组件:

  • CSSTransition用于通过不同CSS的指定形式来展现动画,它有-enter(入场动画初始状态,第一帧),-enter-active(入场动画进行时),-enter-done(入场完成后的样式,一般就是-enter-active所指定的末状态,可以不指定),-exit(离场动画初始状态,第一帧),-exit-active(离场状态进行时),-exit-done(与enter-done类似,同样也几乎没有太大意义)这几个关键的CSS类别。 而CSSTransion有以下几个关键的属性:in,timeout,classNames(注意是classNames,不是className),in属性就是动画开关,classNames即为前文所提到CSS属性名称的前缀部分,timeout即为动画维持时间。
  • TransitionGroup组件,如同它的字面意义,它用于管理一组的过渡组件(比如上文的CSSTransion组件,以及用于其他平台的Transition组件),也就是说,它的子组件,一般是包裹着CSSTransion/Transion组件的组件,它的子组件CSSTransion/Transion上必须指定key属性,利用React根据key值进行diff算法的特性,当发生状态改变的时候,它会暂时保留原本需要移除或变化的子组件,并执行CSSTransion/Transion指定的动画。

​ 简单来说,CSSTransion组件用于进行单个组件的动画过程,而通过TransitionGroup可以对多个由 CSSTransion构成的组件进行管理,而在路由切换这一过程中,本质上就是两个view级别(视图级别)组件的切换过程,这一过程中,在必定存在一个如下图所示的过程: ​ 也就是说,A与B在进行动画切换的时候必定同时存在,这时候就需要使用到TransitionGroup了。 ​