react-transition-group实现多元素之间的动画

TransitionGroup配合CSSTransition

  • 回到文档中,我们可以看到有react-transition-group有**四个组件:Transition、CSSTransition、SwitchTransition、TransitionGroup**。
  • 上一篇笔记我们学习了使用CSSTransition实现单个元素的动画效果。
  • 如果我们想实现多个元素之间的动画效果,就要**使用TransitionGroup配合CSSTransition**:TransitionGroup写在 所有被控制的 DOM元素/组件 的外部,管理所有;CSSTransition写在 具体(单个) DOM元素/组件 的外部,管理单个动画效果。
  • TransitionGroup文档和例子

注意

  1. 实现多个元素之间的动画效果时,不再需要CSSTransition标签中的属性in={this.state.show}
  2. key值加载循环的单个组件的最外层标签上。(当我们使用CSSTransition标签包裹 其他标签 来控制动画效果时,这个 被控制标签 的key值就要放到CSSTransition标签内。)
  3. setState()有一个参数prevState表示上一次的state数据
  4. JS变量/表达式 写在 JSX语法中,需要使用{}包裹。

例子

实现效果
每一次点击按钮就会在页面上添加一个div显示“hello world”,并在所有div元素上都显示出动画效果(入场动画(执行的是fade-enter前缀的三个样式))。

先实现点击按钮添加item

App.js中,暂时隐藏App.js中的CSSTransition标签,,删去div标签和handleToggle函数,给按钮绑定点击事件函数handleAddItem,每次点击按钮就在页面上添加一个div标签“item”。

1
<button onClick={this.handleAddItem}>toggle</button>

state中的 布尔值show 换成 数组list,用于存放每次点击后添加的div标签(“item”)的数据。并绑定事件函数的this指向:

1
2
3
4
5
6
7
constructor(props) {
super(props);
this.state = {
list: []
}
this.handleAddItem = this.handleAddItem.bind(this);
}

在按钮的事件绑定函数handleAddItem,每次点击后都使用setState()把新的item存到list数组中(记住setState有一个参数prevState表示上一次的state数据),使用return返回一个对象

1
2
3
4
5
6
7
handleAddItem() {
this.setState((prevState) => {
return {
list: [...prevState.list, "item"]
}
})
}

在render函数的return中,使用map()循环展示list中的每一项item,并将其放到div标签中返回(注意:JS变量/表达式 写在 JSX语法中,需要使用{}包裹):
【**注意:这里返回的是使用map产生的数组,不能用forEach。在jsx渲染中,如果这个变量是一个数组,则会展开这个数组的所有成员**】

1
2
3
4
5
6
7
{
this.state.list.map((item,index) => {
return (
<div key={index}>{item}</div>
)
})
}

此时每点击一次按钮就能在页面上添加一个“item”,但还没有动画效果:
点击两次按钮后

添加动画效果

**在App.js中引入组件TransitionGroup**(相关文档):

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

**使用TransitionGroup配合CSSTransition**:TransitionGroup写在 所有被控制的 DOM元素/组件 的外部,管理所有;CSSTransition写在 具体(单个) DOM元素/组件 的外部,管理单个动画效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<TransitionGroup>
{
this.state.list.map((item, index) => {
return (
<CSSTransition
timeout={1000}
classNames="fade"
unmountOnExit
onEntered={(el) => { el.style.color = "blue" }}
appear={true}
key={index}
>
<div>{item}</div>
</CSSTransition>
)
})
}
</TransitionGroup>

((key值加载循环的单个组件的最外层标签上。(当我们使用CSSTransition标签包裹 div标签 来控制动画效果时,这个 div标签 的key值就要放到CSSTransition标签内。)

结果

此时每一次点击的按钮都会有入场动画(执行的是fade-enter前缀的三个样式):
结果


,