React-Router Animation 动画

在前面的文章中的组件切换,都是直来直往,没有任何过渡,然后这并不符合真实项目场景,通常在项目中,切换不同的组件,都会添加一些动画效果。React 中可以使用 react-addons-css-transition-group 来实现动画效果。

假定我们要实现的页面:上面4个 tab ,分别对应不同的4个组件,点击 tab 切换到不同的组件,在这里使用不同的颜色来表示不同的组件,而不是真正的4个不同的组件。

step1: 定义样式

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
const styles = {}
styles.root = {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0
}
styles.nav = {
padding: 0,
margin: 0,
position: 'absolute',
top: 0,
height: '40px',
width: '100%',
display: 'flex'
}
styles.navItem = {
textAlign: 'center',
flex: 1,
listStyleType: 'none',
padding: '10px'
}
styles.content = {
...styles.root,
top: '40px',
textAlign: 'center'
}
styles.hsl = {
...styles.root,
color: 'white',
paddingTop: '20px',
fontSize: '30px'
}

root 为根布局,navtab 父布局,navItem 表示每一个 tabcontent 表示每一个 tab 对应的组件的容器,hsl 表示内容组件。

step2: 定义 tab 组件

1
2
3
4
5
const NavLink = (props) => (
<li style={styles.navItem}>
<Link {...props} style={{ color: 'inherit' }}/>
</li>
)

该组件是对 Link 组件的包装,仅仅是添加了不同的样式。

step3: 定义 hsl 内容组件

1
2
3
4
5
6
7
const HSL = ({match: {params}}) => (
<div style={{
...styles.root,
...styles.hsl,
background: `hsl(${params.h}, ${params.s}%, ${params.l}%)`
}}>hsl({params.h}, {params.s}%, {params.l}%)</div>
)

组件使用 params 中的参数来设置背景颜色。

step4: 定义 root 组件

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 ReactCSSTransitionGroup from 'react-addons-css-transition-group'
import {
BrowserRouter as Router,
Route,
Link,
Redirect
} from 'react-router-dom'
const AnimComponent = ({location})=> {
return (
<div style={styles.root}>
<Route exact path="/" render={() => {
return (<Redirect to="/10/90/50"/>)}}/>
<ul style={styles.nav}>
<NavLink to="/10/90/50">Red</NavLink>
<NavLink to="/120/100/40">Green</NavLink>
<NavLink to="/200/100/40">Blue</NavLink>
<NavLink to="/310/100/50">Pink</NavLink>
</ul>
<div style={styles.content}>
<ReactCSSTransitionGroup
transitionName="fade"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
{/*
这里和使用 ReactCSSTransitionGroup 没有区别,
唯一需要注意的是要把地址(location)传入
「Route」里使它可以在动画切换的时候匹配之前的
地址,否则就不会有动画效果。
*/}
<Route
location={location}
key={location.key}
path="/:h/:s/:l"
component={HSL}
/>
</ReactCSSTransitionGroup>
</div>
</div>
);
}

step5: 定义动画效果

1
2
3
4
5
6
7
8
9
.fade-enter {
opacity: 0;
z-index: 1;
}
.fade-enter.fade-enter-active {
opacity: 1;
transition: opacity 250ms ease-in;
}

关于 ReactCSSTransitionGroup 请参考 Link