使用react-transition-group实现动画

复习:三目运算符b?x:y

对于条件表达式b ? x : y,先计算条件b,然后进行判断。
如果b的值为true,计算x的值,运算结果为x的值;
否则,计算y的值,运算结果为y的值。


React中实现CSS过渡动画

  • 实现功能:点击button实现hello的显示或隐藏
  • 注意:render函数中只能return一个父标签,可以借助react的Fragment占位符,它并不会被渲染成任何一个标签。(Fragment在react库中,需引用才能使用)
  • CSS中: opacity属性 为1时显示,为0时隐藏。transition属性 可实现过渡效果
    【opacity 不透明;transition 过渡】

例子
1.将TodoList文件夹中src文件夹下删为仅剩一个index.js文件
在**index.js中引入并挂载 组件APP 到 root节点 上**:

1
2
3
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

2.新建**APP.js编写 组件APP 的 render函数** ,写出页面上的两个元素div和button:

1
2
3
4
5
6
7
8
render() {
return (
<Fragment>
<div>hello world</div>
<button>toggle</button>
</Fragment>
);
}

注意,Fragment需要先引用才能使用

1
import React, { Component, Fragment } from 'react';

两个元素

3.补充APP.js中的 constructor构造函数 ,将 div 显示与否 的 决定属性show 存在state中,使用show的值给div加上一个className属性,给button绑定一个 onclick事件函数 handleToggle,点击时让show在false与true之间进行变换(记得绑定函数handleToggle的this指向):

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
import React, { Component, Fragment } from 'react';

class App extends Component {
constructor(props) {
super(props);
this.state = {
show: true
}
this.handleToggle = this.handleToggle.bind(this);
}

render() {
return (
<Fragment>
<div className={this.state.show ? "show" : "hide"}>hello world</div>
<button onClick={this.handleToggle}>toggle</button>
</Fragment>
);
}

handleToggle() {
this.setState(() => {
return ({
show: this.state.show ? false : true
})
})
}
}

export default App;

结果:虽然点击按钮看不到效果变化,但实际className还是发生了改变,所以接下来我们就去设置CSS
点击按钮前后

4.设置CSS.js并在 APP.js 中使用import "./style.css";进行引用,CSS.js:

1
2
3
4
5
6
.show{
opacity: 1;
}
.hide{
opacity: 0;
}

结果:此时点击按钮可使“hello”消失/显示,但没有过渡效果,我们可以加上 transition属性 实现过渡效果

1
2
3
4
5
6
7
8
.show{
opacity: 1;
transition: all 1s ease-in;
}
.hide{
opacity: 0;
transition: all 1s ease-in;
}

React中使用CSS动画效果

  • 实现功能:点击按钮时,hello经过红色、绿色、蓝色过渡,最后显示/消失。
  • 什么叫CSS动画效果:通过 @keyframes 定义一些CSS动画,然后在选择器中通过 animation属性 进行动画的调用
  • CSS3中 animation属性 有 forwards属性值 :可以使动画结束后保留最后一个效果的样式.

例子
修改style.css通过 @keyframes 定义一些CSS动画,然后在选择器中通过 animation属性 进行动画的调用。(使用 animation属性 代替 opacity属性):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.show{
opacity: 1;
transition: all 1s ease-in;
}
.hide{
animation: hide-item 2s ease-in;
transition: all 1s ease-in;
}
@keyframes hide-item{
0%{
opacity: 1;
color: red;
}
50%{
opacity: 0.5;
color: green;
}
100%{
opacity: 0;
color: blue;
}
}

结果
此时可以发现动画效果已实现,但是蓝色以后hello又回到黑色,并未消失,这是因为动画执行结束后,最后一个效果不会被保持下来
CSS3中有 forwards属性值 ,它可以使动画结束后保留最后一个效果的样式

1
2
3
4
.hide{
animation: hide-item 2s ease-in forwards;
transition: all 1s ease-in;
}

结果:可以发现动画效果后hello消失。

给 显示 也设置动画效果:

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
.show{
animation: show-item 2s ease-in forwards;
transition: all 1s ease-in;
}
.hide{
animation: hide-item 2s ease-in forwards;
transition: all 1s ease-in;
}
@keyframes show-item{
0%{
opacity: 0;
color: red;
}
50%{
opacity: 0.5;
color: green;
}
100%{
opacity: 1;
color: blue;
}
}
@keyframes hide-item{
0%{
opacity: 1;
color: red;
}
50%{
opacity: 0.5;
color: green;
}
100%{
opacity: 0;
color: blue;
}
}

使用react-transition-group实现动画

react-transition-group:react动画的第三方模块
上面我们讲解的 CSS动画 比较局限,涉及到 JS动画 的部分就无法处理。借助 react-transition-group 这个第三方模块 ,我们可以更加方便的做一些动画效果。

安装react-transition-group模块

进入github - 搜索react-transition-group - 选择星标最多的 - 下拉点击Main documentation(主文档) - 安装提示,在命令行中输入

1
2
# yarn
yarn add react-transition-group

重新启动项目

1
npm start

接着回到文档可以看到下面有 四个 动画组件
四个 动画组件 选择

学习CSSTransition组件

  • **我们主要讲解CSSTransition**。
  • Transition组件 是比CSSTransition组件更低层的存在,当我们利用CSSTransition组件无法实现一些效果时,可以到Transition组件中去找。

官方文档的 Example 中可以看到 <CSSTransition> 有以下属性(/JS钩子)

1
2
3
4
5
6
7
8
<CSSTransition
in={showMessage}
timeout={300}
classNames="alert"
unmountOnExit
onEnter={() => setShowButton(false)}
onExited={() => setShowButton(true)}
>

in属性

in属性 告诉CSSTransition 被控制元素的 入场/出场状态CSSTransition需要给 被控制的元素 增加/删除 一些样式,而 in属性 就是告诉了CSSTransition 属性值 false->true时 入场,true->false时 出场。

timeout属性

动画持续的毫秒数(1000毫秒=1秒)

classNames属性

  • **注意有个s**,属性值为 自动挂载的样式 的前缀。(也就是说它决定了该组件的样式都有哪些)
  • classNames属性值可以使官方文档中给定的也可以是自定义的字符串属性值决定了 自动挂载的样式 的前缀
  • 比如下面的**样式fade-appear的前缀就是fade,那么我们就要设置classNames='fade'**,这样对应的样式才会生效。

unmountOnExit属性

该属性不需要属性值,添加该属性后,被控制的元素完成出场动画后将直接消失在页面(不会留下一个空白位置)。
例子

JS钩子

  • 钩子 相当于 生命周期函数,他们都是某一时刻会自动执行的函数。
  • 属性值就是个JS钩子(函数)
  • 该函数可以接收一个自命名参数,该参数 指 被CSSTransition控制的元素

onEnteronEnteringonEntered

  • onEnter:当入场动画执行的第一个时刻,onEnter钩子(函数)就会被自动执行
  • onEntering:当入场动画执行第二帧时,onEntering钩子(函数)就会被自动执行
  • onEntered:当入场动画执行完成后,onEntered钩子(函数)就会被自动执行

onExitonExitingonExiting

  • onExit:当出场动画执行的第一个时刻,onExit钩子(函数)就会被自动执行
  • onExiting:当出场动画执行第二帧时,onExiting钩子(函数)就会被自动执行
  • onExiting:当出场动画执行完成后,onExited钩子(函数)就会被自动执行

自动挂载的样式(classNames)

  • 官方文档中 Example 下给出了很多自动挂载的样式(classNames),比如fade-appear, fade-appear-active, fade-appear-done, fade-enter, fade-enter-active, fade-enter-done, fade-exit, fade-exit-active, fade-exit-done.
    • 注意:这些样式的前提是CSSTransition组件的classNames="fade"classNames属性值是自定义的字符串,属性值决定了样式的前缀
  • 使用方法:.fade-appear{color: red;}
  • 需要先设置CSSTransition标签的属性classNames="fade"才能使用这些fade前缀的样式。
  • 需要**先设置CSSTransition标签的属性appear={true},才能使用fade-appear, fade-appear-active, fade-appear-done**。

入场动画相关的样式

  • 入场动画相关的样式:fade-enterfade-enter-activefade-enter-done
  • fade-enter入场动画执行的第一个时刻CSSTransition会往 被控制的元素上 增加fade-enter样式。
  • fade-enter-active入场动画执行的第二个时刻到入场动画执行完成之前,此时 被控制的元素上 会一直有fade-enter-active样式。
  • fade-enter-done整个入场动画执行完成之后fade-enter-done样式会被增加并保持在 被控制的元素上

出场动画相关的样式

  • 出场动画相关有:fade-exitfade-exit-activefade-exit-done
  • fade-exit出场动画执行的第一个时刻CSSTransition会往 被控制的元素上 增加fade-exit样式。
  • fade-exit-active出场动画执行的第二个时刻到出场动画执行完成之前,此时 被控制的元素上 会一直有fade-exit-active样式。
  • fade-exit-done整个入场动画执行完成之后fade-exit-done样式会被增加并保持在 被控制的元素上

刷新页面执行的动画相关样式

  • 刷新页面执行的动画相关样式有:**fade-appearfade-appear-activefade-appear-done**
  • 在页面刷新,DOM元素的第一次渲染时的动画效果就由这些样式来决定。
  • 注意:需要**先设置CSSTransition标签的属性appear={true},才能使用fade-appear, fade-appear-active, fade-appear-done**。
  • fade-appear-done不设置时,页面显示默认的状态作为动画效果的最后一个状态保持。

CSSTransition例子

之前我们是自己在state中设置一个show值用于改变div的 className(样式名字),达到 div元素显示/删除 的工作,现在**CSSTransition会帮我们完成一些 样式名字 的 添加/删除 工作,只需要使用<CSSTransition>标签包裹需要被控制的元素(div)并进行属性设置**即可。

App.js引用CSSTransition组件:

1
import { CSSTransition } from 'react-transition-group';

使用**CSSTransition标签包裹需要被控制的div标签**:

1
2
3
4
5
6
7
<CSSTransition
in={this.state.show}
timeout={1000}
classNames="fade"
>
<div>hello world</div>
</CSSTransition>

将原本的**style.css**删除掉,改为:

1
2
3
4
5
6
7
8
9
10
.fade-enter{
opacity: 0;
}
.fade-enter-active{
opacity: 1;
transition: opacity 1s ease-in;
}
.fade-enter-done{
opacity: 1;
}

结果:在页面上可以看到点击按钮,show值由false->true时,页面有动画效果(入场效果)。接下来增加 出场动画

1
2
3
4
5
6
7
8
9
10
.fade-exit{
opacity: 1;
}
.fade-exit-active{
opacity: 0;
transition: opacity 1s ease-in;
}
.fade-exit-done{
opacity: 0;
}

效果:做到这里完成的效果与上一个例子效果一样,看起来似乎并没有简化,但是下面增加的就是CSSTransition带来的简化

使用unmountOnExit属性

在**CSSTransition标签内增加unmountOnExit属性,该属性不需要属性值**。
添加该属性后,被控制的元素完成出场动画后将直接消失在页面(不会留下一个空白位置)。
例子

使用JS钩子onEntered

实现效果:hello显示完成后变为红色。
实现方法:我们可以在CSS中通过改变.fade-enter-done选择器内的color实现,也可以通过 JS钩子onEnter 实现

CSSTransition标签内增加:

1
onEntered={(el) => { el.style.color = "blue" }}

appear属性与对应的样式

做到这儿可以发现一个小问题:页面刚刷新时并不会显示动画效果,如果我们希望元素首次挂载在页面上就显示动画效果,可以使用appear属性,但appear属性对应的CSS样式并不是.fade-enter那几个,是fade-appear前缀的三个样式。

App.js中添加CSSTransition标签的appear属性:

1
appear={true}

style.css中增加.fade-appear.fade-appear-active:

1
2
3
4
5
6
7
.fade-enter,.fade-appear{
opacity: 0;
}
.fade-enter-active,.fade-appear-active{
opacity: 1;
transition: opacity 1s ease-in;
}

,