(32)React 拓展——② 使用 react-transition-group 实现动画 | React 基础理论实操
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
1 CSSTransition
紧接上一篇代码,本篇我们用 React 动画的第三方模块 react-transition-group 来轻松实现更加复杂的动画效果。
1️⃣安装这个模块:
npm install react-transition-group --save
2️⃣本节我们主要讲解 CSSTransition 的使用(Transition 是更底层的组件,当 CSSTransition 实现不了我们的需求时,可以去查查 Transition 的 API。而 TransitionGroup 的话,我们会在下一节讲解!),跟着官方文档的“例子”进行操作:
打开 App.js
文件:
import React, { Component, Fragment } from "react";
// 2️⃣-①:引入 CSSTransition 动画组件;
import { CSSTransition } from 'react-transition-group';
import "./style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
show: true
}
this.handleBtnToggle = this.handleBtnToggle.bind(this);
}
render() {
return (
<Fragment>
{/*
❗️❗️❗️2️⃣-②:有了 CSSTransition 后,我们就不需要自己去进行样式的添加和移除了!
<div className={this.state.show ? "show" : "hide"}>hello, qdywxs.</div>
*/}
{/*
2️⃣-③:取而代之,我只需要在 div 元素的外层嵌套一个 CSSTransition 组件即可。
CSSTransition 会自动帮我们做一些 class 的增加、移除的工作;
*/}
<CSSTransition>
<div>hello, qdywxs.</div>
</CSSTransition>
<button onClick={this.handleBtnToggle}>toggle</button>
</Fragment>
);
}
handleBtnToggle() {
this.setState({
show: this.state.show ? false : true
})
}
}
export default App;
❗️❗️❗️2️⃣-④:接着需要对 CSSTransition 做一些设置;
🚀在具体的代码编写之前,我们先熟悉一下基本的理论知识:
1. CSSTransition 组件中重要的 API 解析
-
in
:Boolean,控制组件显示与隐藏。true
显示,false
隐藏; -
timeout
:Number,延迟,涉及到动画状态的持续时间。可传入一个对象,如{exit: 300, enter: 500}
来分别设置“进入”和“离开”的延时; -
classNames
:String,动画进行时给元素添加的类名。一般利用这个属性来设计动画!(❗️特别注意:是classNames
而不是className
!) -
unmountOnExit
:Boolean,这是一个很实用的 API,它为我们节省了很多精力。为true
时——组件为隐藏状态时移除组件;为false
时——组件保持动画结束时的状态而不移除元素(一般要设成true
)。
2. 类名的添加
动画进行时,以 classNames="fade"
为例,CSSTransition 将自动依次为要执行动画的元素添加以下类名:
-
fade-enter
-
fade-enter-active
-
fade-enter-done
-
fade-exit
-
fade-exit-active
-
fade-exit-done
我们也可以单独指定每一个类名:
classNames={{
enter: "my-enter",
enterActive: "my-active-enter",
enterDone: "my-done-enter",
exit: "my-exit",
exitActive: "my-active-exit",
exitDone: "my-done-exit"
}}
3. 每个类名的添加时机
-
enter
:当元素进入时添加; -
enter-active
:当元素进入到页面后添加。它与enter
的主要差别是——enter-active
是在元素已经添加到页面后才会添加enter-active
,而enter
在元素添加到页面时已经携带; -
enter-done
:动画执行完毕后添加。动画时长取决于timeout
; -
exit
:元素离开时添加。离开动画时长取决于timeout
; -
exit-active
:同exit
; -
exit-done
:离开动画完成后添加(仅在unmountOnExit
为false
时有效)。
2️⃣-⑤:基础理论知识介绍完后,我们直奔 App.js
文件进行代码的编写;
import React, { Component, Fragment } from "react";
import { CSSTransition } from 'react-transition-group';
import "./style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
show: true
}
this.handleBtnToggle = this.handleBtnToggle.bind(this);
}
render() {
return (
<Fragment>
{/* ❗️2️⃣-⑥:对 CSSTransition 进行设置; */}
<CSSTransition
in={this.state.show}
timeout={1000}
classNames="fade"
unmountOnExit={true}
>
<div>hello, qdywxs.</div>
</CSSTransition>
<button onClick={this.handleBtnToggle}>toggle</button>
</Fragment>
);
}
handleBtnToggle() {
this.setState({
show: this.state.show ? false : true
})
}
}
export default App;
❗️❗️❗️2️⃣-⑦:打开 style.css
文件(清空之前的代码),我们在里边定义动画“进行时”各阶段的效果(🏆CSSTransition 已自动为我们添加了动画各阶段对应的 class
,我们只需要给各 class
添加对应的效果即可);
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 1s ease-in;
}
fade-enter-done {
opacity: 1;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 1s ease-in;
}
fade-exit-done {
opacity: 0;
}
返回页面查看效果:
3️⃣我们继续查阅官方文档,拉到最下边,官方为我们提供了很多“钩子函数”。“钩子函数”是什么?它是会在适当的时候自动执行的函数!
利用这些“钩子函数”,我们就可以用 JS 来控制一些样式了。如(打开 App.js
文件):
import React, { Component, Fragment } from "react";
import { CSSTransition } from 'react-transition-group';
import "./style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
show: true
}
this.handleBtnToggle = this.handleBtnToggle.bind(this);
}
render() {
return (
<Fragment>
{/*
❗️❗️❗️在这里定义一个“钩子函数”,当“入场动画”结束之后,
onEntered 自动执行!
❗️里边的参数 el 指的就是 CSSTransition 内部包裹的这个 div 元素!
*/}
<CSSTransition
in={this.state.show}
timeout={1000}
classNames="fade"
unmountOnExit={true}
onEntered={(el) => {
el.innerHTML="hello, 前端一万小时.";
el.style.color="red";
}}
>
<div>hello, qdywxs.</div>
</CSSTransition>
<button onClick={this.handleBtnToggle}>toggle</button>
</Fragment>
);
}
handleBtnToggle() {
this.setState({
show: this.state.show ? false : true
})
}
}
export default App;
返回页面查看效果:
❓4️⃣上边的动画效果有个问题:页面初次打开时(刷新页面),动画效果是不执行的!怎样解决这个问题呢?
答:CSSTransition 的 appear
属性可以帮助我们实现——页面一打开,动画效果就生效!
打开 App.js
文件:
import React, { Component, Fragment } from "react";
import { CSSTransition } from 'react-transition-group';
import "./style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
show: true
}
this.handleBtnToggle = this.handleBtnToggle.bind(this);
}
render() {
return (
<Fragment>
{/* ❗️4️⃣-①:增加一个 appear 属性; */}
<CSSTransition
in={this.state.show}
timeout={1000}
classNames="fade"
unmountOnExit={true}
appear={true}
onEntered={(el) => {
el.innerHTML="hello, 前端一万小时.";
el.style.color="red";
}}
>
<div>hello, qdywxs.</div>
</CSSTransition>
<button onClick={this.handleBtnToggle}>toggle</button>
</Fragment>
);
}
handleBtnToggle() {
this.setState({
show: this.state.show ? false : true
})
}
}
export default App;
4️⃣-②:当用了 appear
属性后,CSSTransition 会帮助我们干一件事——它会在入场动画的第一帧增加一个名为 fade-appear
的 class
;还会在整个动画进行过程中增加一个名为 fade-appear-active
的 class
;
打开 style.css
文件:
.fade-enter, .fade-appear { /* ❗️增加 fade-appear */
opacity: 0;
}
.fade-enter-active, .fade-appear-active { /* ❗️增加 fade-appear-active */
opacity: 1;
transition: opacity 1s ease-in;
}
fade-enter-done {
opacity: 1;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 1s ease-in;
}
fade-exit-done {
opacity: 0;
}
返回页面查看效果:
2 TransitionGroup
Transition Group 可以帮助我们实现多个元素的动画效果。
❓需求:紧接上边的代码,当我每点击一次 toggle 按钮时,页面都会相应显示一行 hello, qdywxs.
。且,显示的时候都会有动画效果(入场动画结束后,会变成红色的 hello, 前端一万小时.
)。
答:
1️⃣打开 App.js
文件(将里边的代码清空),我们先来实现“点击” --> “显示”的逻辑:
import React, { Component, Fragment } from "react";
import "./style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
list:[]
}
this.handleAddItem = this.handleAddItem.bind(this);
}
render() {
return (
<Fragment>
{
this.state.list.map((item, index) => {
return (
<div key={index}>hello, qdywxs.</div>
)
})
}
<button onClick={this.handleAddItem}>toggle</button>
</Fragment>
);
}
handleAddItem() {
this.setState((prevState) => {
return {
list: [...prevState.list, "item"]
}
})
}
}
export default App;
看下页面效果:
2️⃣实现每一项 hello, qdywxs.
出现时,都有动画效果(请对照 TransitionGroup 官方文档学习并自行拓展):
import React, { Component, Fragment } from "react";
// 2️⃣-①:引入 CSSTransition 和 TransitionGroup 这两个“组件”;
import {
CSSTransition,
TransitionGroup,
} from "react-transition-group";
import "./style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
list:[]
}
this.handleAddItem = this.handleAddItem.bind(this);
}
render() {
return (
// 2️⃣-②:参照官方文档例子,给要添加动画的“多个元素”的最外层包裹一个 TransitionGroup 标签;
/*
2️⃣-③:给单个元素包裹 CSSTransition 标签(这个和上文讲的做法一模一样,
可以直接拷贝过来,❗️但要去掉属性 in);
*/
<Fragment>
<TransitionGroup>
{
this.state.list.map((item, index) => {
return (
<CSSTransition
timeout={1000}
classNames="fade"
unmountOnExit={true}
appear={true}
onEntered={(el) => {
el.innerHTML="hello, 前端一万小时.";
el.style.color="red";
}}
key={index}
>
<div>hello, qdywxs.</div>
</CSSTransition>
)
})
}
</TransitionGroup>
<button onClick={this.handleAddItem}>toggle</button>
</Fragment>
);
}
handleAddItem() {
this.setState((prevState) => {
return {
list: [...prevState.list, "item"]
}
})
}
}
export default App;
返回页面查看效果:
祝好,qdywxs ♥ you!
转载自:https://juejin.cn/post/7313589252172021794