React@16.x(34)动画(中)

目录

接上面文章 React动画(上)

3,SwitchTransition

官方文档

在上篇文章中,用 CSSTransition 做了一个动画:

可以看到,这2个元素的动画是同时发生的,因为使用同一个状态变量控制的(代码参考上篇文章)

SwitchTransition 组件是专门用来做切换动画 的,并且2个元素的动画是有先后顺序的。

元素1完成退出动画后,元素2再开始进入动画。

3.1,原理

默认情况下(mode="out-in"),通过改变状态变量来改变 key 值,才能开始切换动画,

key 属性替换了之前的 in 属性。

如果默认 state=true,渲染元素1,则切换状态时的动画过程:

  1. 先给元素1添加类名 exit exit-active,元素1执行退出动画。
  2. 等元素1的退出动画完成(过渡时间结束),再给元素2添加类名 enter enter-active 执行进入动画。
  3. 等元素2的进入动画完成,类名切换为 enter-done

所以,只需要设置这5个类名对应的样式即可。

如果进入动画结束后,用的默认样式(比如: opacity: 1)那类名 enter-done 也不用设置。

3.1.2,key

因为会将退出动画和进入动画对应的类名,设置到对应的元素上,来实现切换动画。

所以如果不设置,那所有的类名会加到同一个元素上,结果是该元素无限进入循环动画(退出-进入-退出...)

key 只要保证唯一,能区分为2个元素即可。

3.1.2,mode

默认 out-in,具体动画过程上面已经介绍了。

in-out,如果默认 state=true,渲染元素1,则切换状态时的动画过程:

  1. 保持元素1不变,为元素2添加enter enter-active 执行进入动画。
  2. 过渡时间结束,元素2的类名变为 enter-done,同时为元素1添加类名 exit exit-active,开始退出动画。
  3. 过渡时间结束,元素1被移除。

相当于先执行了一次元素2的进入动画,之后再开始执行元素1的退出动画。

3.2,举例

js 复制代码
import { CSSTransition, SwitchTransition } from "react-transition-group";
import { useRef, useState } from "react";
import "./App.css";

export default function App() {
    const [state, setState] = useState(true);
    return (
        <SwitchTransition>
            <CSSTransition key={state} timeout={500}>
                <button onClick={() => setState(!state)}>{state ? "状态1" : "状态2"}</button>
            </CSSTransition>
        </SwitchTransition>
    );
}
css 复制代码
/* App.css */
.enter {
    opacity: 0;
}
.enter-active {
    opacity: 1;
    transition: opacity 1s;
}

.exit {
    opacity: 1;
}
.exit-active {
    opacity: 0;
    transition: opacity 1s;
}

效果:

同样的,要在过渡完成后执行 transitionend 事件,可以:

js 复制代码
export default function App() {
    const [state, setState] = useState(true);
    const refBtn1 = useRef(null);
    const refBtn2 = useRef(null);
    const nodeRef = state ? refBtn1 : refBtn2;
    return (
        <SwitchTransition>
            <CSSTransition
                key={state}
                timeout={1000}
                nodeRef={nodeRef}
                addEndListener={() => {
                    nodeRef.current.addEventListener(
                        "transitionend",
                        () => {
                            console.log("过渡结束");
                        },
                        { once: true }
                    );
                }}
            >
                <button ref={nodeRef} onClick={() => setState((state) => !state)}>
                    {state ? "状态1" : "状态2"}
                </button>
            </CSSTransition>
        </SwitchTransition>
    );
}

3.3,结合 animate.css

animate 样式举例1animate 样式举例2

安装:

bash 复制代码
npm install animate.css -S

样例完整代码:

js 复制代码
import { CSSTransition, SwitchTransition } from "react-transition-group";
import { useState } from "react";
import "animate.css";

export default function App() {
    const [state, setState] = useState(true);
    return (
        <SwitchTransition>
            <CSSTransition
                key={state}
                timeout={1000}
                classNames={{
                    appearActive: "animate__fadeInRight",
                    enterActive: "animate__fadeInRight",
                    exitActive: "animate__fadeOutLeft",
                }}
            >
                <button className="animate__animated" onClick={() => setState(!state)}>
                    {state ? "状态1" : "状态2"}
                </button>
            </CSSTransition>
        </SwitchTransition>
    );
}

效果:

4,TransitionGroup

官方文档

它接收一组 CSSTransitionTransition,统一控制它们的进入和退出动画。

SwitchTransition 一样,会添加对应的类名来实现动画。

经典例子:待办列表,可以动态新增或删除待办项,同时为每一项都应用动画。

js 复制代码
import { TransitionGroup, CSSTransition } from "react-transition-group";
import { useState } from "react";
import { v4 as uuidv4 } from "uuid";
import "./App.css";

export default function App() {
    const [todoList, setTodoList] = useState([
        { id: uuidv4(), content: "学习" },
        { id: uuidv4(), content: "吃饭" },
        { id: uuidv4(), content: "睡觉" },
    ]);
    return (
        <>
            <TransitionGroup>
                {todoList.map((item) => (
                    <CSSTransition key={item.id} timeout={500}>
                        <div>
                            <span>{item.content}</span>
                            <button
                                onClick={() => {
                                    const resultItem = todoList.filter((f) => f.id !== item.id);
                                    setTodoList(resultItem);
                                }}
                            >
                                删除
                            </button>
                        </div>
                    </CSSTransition>
                ))}
            </TransitionGroup>
            <button
                onClick={() => {
                    const answer = window.prompt();
                    setTodoList([
                        ...todoList,
                        {
                            id: uuidv4(),
                            content: answer,
                        },
                    ]);
                }}
            >
                新增
            </button>
        </>
    );
}

4.1,其他属性

4.1.2,appear

统一添加加载动画,同时会有 appearappear-activeappear-done 类名。

4.1.2,component

控制渲染的容器的节点类名,默认 divnull 表示不渲染节点。

html 复制代码
<TransitionGroup appear component="ul">

4.1.3,classNames

component 对应节点的类名,不是动画类名前缀。

动画类名前缀,还是要添加到 CSSTransition 组件上。


以上。

相关推荐
dorabighead11 分钟前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
css趣多多29 分钟前
案例自定义tabBar
前端
姑苏洛言2 小时前
DeepSeek写微信转盘小程序需求文档,这不比产品经理强?
前端
林的快手2 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
匹马夕阳2 小时前
ECharts极简入门
前端·信息可视化·echarts
bug总结2 小时前
新学一个JavaScript 的 classList API
开发语言·javascript·ecmascript
网络安全-老纪3 小时前
网络安全-js安全知识点与XSS常用payloads
javascript·安全·web安全
API_technology3 小时前
电商API安全防护:JWT令牌与XSS防御实战
前端·安全·xss
yqcoder3 小时前
Express + MongoDB 实现在筛选时间段中用户名的模糊查询
java·前端·javascript
十八朵郁金香3 小时前
通俗易懂的DOM1级标准介绍
开发语言·前端·javascript