react-transition-group
这个库主要用于在 React 应用中管理组件的进入和离开动画。让我们从基础开始,逐步深入。
react-transition-group 主要包含四个组件:
- Transition
- CSSTransition
- SwitchTransition
- TransitionGroup
Transition
这是最基本的组件,它不使用 CSS 类,而是暴露了不同的状态作为函数参数。
在这个例子中,Transition 组件接受一个 in prop,用来控制是否显示内容。timeout 定义了过渡的持续时间。
js
import { Transition } from 'react-transition-group';
import React, { useState } from 'react';
const duration = 300;
const defaultStyle = {
transition: `opacity ${duration}ms ease-in-out`,
opacity: 0,
}
const transitionStyles = {
entering: { opacity: 1 },
entered: { opacity: 1 },
exiting: { opacity: 0 },
exited: { opacity: 0 },
};
function App() {
const [inProp, setInProp] = useState(false);
return (
<div>
<Transition in={inProp} timeout={duration}>
{state => (
<div style={{
...defaultStyle,
...transitionStyles[state]
}}>
I'm a fade Transition!
</div>
)}
</Transition>
<button onClick={() => setInProp(!inProp)}>
Click to Toggle
</button>
</div>
);
}CSSTransition
这个组件在 Transition 的基础上增加了 CSS 类的支持,使得使用 CSS 来定义过渡效果变得更加容易。
例子:根据 activeIndex 切换内容
js
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import React, { useState } from 'react';
import './styles.css';
function App() {
const [activeIndex, setActiveIndex] = useState(1);
const items = [
{ id: 1, text: "Content A" },
{ id: 2, text: "Content B" },
];
return (
<div>
<TransitionGroup>
<CSSTransition
key={activeIndex}
timeout={300}
classNames="fade"
>
<div>
{items.find(item => item.id === activeIndex).text}
</div>
</CSSTransition>
</TransitionGroup>
<button onClick={() => setActiveIndex(activeIndex === 1 ? 2 : 1)}>
Toggle Content
</button>
</div>
);
}对应的CSS:
css
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 300ms ease-in;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 300ms ease-in;
}在这个例子中,当 activeIndex 改变时,CSSTransition 会自动应用相应的 CSS 类来实现淡入淡出效果。
CssTransition中重要的API解析
- in: 控制组件显示和隐藏。
- timeout: 涉及显示和隐藏的时间。{exit:300,enter:500} 表示退出和进入的时间。
- classNames: 定义 CSS 类的前缀。注意是 classNames而不是className。
- unmountOnExit: 是否在组件退出时卸载组件。true表示在退出时卸载组件。false表示在保持退出时的状态。
SwitchTransition
这个组件用于在两个组件之间进行过渡。
这个例子展示了如何在两个状态之间平滑切换。
js
import { SwitchTransition, CSSTransition } from 'react-transition-group';
import React, { useState } from 'react';
import './styles.css';
function App() {
const [state, setState] = useState(false);
return (
<SwitchTransition>
<CSSTransition
key={state ? "Goodbye, world!" : "Hello, world!"}
addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
classNames='fade'
>
<button onClick={() => setState(state => !state)}>
{state ? "Goodbye, world!" : "Hello, world!"}
</button>
</CSSTransition>
</SwitchTransition>
);
}TransitionGroup
这个组件用于管理一组过渡组件,通常用于列表。
js
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import React, { useState } from 'react';
import './styles.css';
function App() {
const [items, setItems] = useState([
{ id: 1, text: 'Buy milk' },
{ id: 2, text: 'Walk the dog' },
{ id: 3, text: 'Do laundry' }
]);
const addItem = () => {
setItems([...items, { id: items.length + 1, text: `New Task ${items.length + 1}` }]);
};
const removeItem = id => {
setItems(items.filter(item => item.id !== id));
};
return (
<div>
<button onClick={addItem}>Add Item</button>
<TransitionGroup>
{items.map(({ id, text }) => (
<CSSTransition
key={id}
timeout={500}
classNames="item"
>
<div>
{text}
<button onClick={() => removeItem(id)}>X</button>
</div>
</CSSTransition>
))}
</TransitionGroup>
</div>
);
}对应的CSS:
css
.item-enter {
opacity: 0;
}
.item-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.item-exit {
opacity: 1;
}
.item-exit-active {
opacity: 0;
transition: opacity 500ms ease-in;
}这个例子展示了如何为列表项添加进入和离开动画。
原理解释
react-transition-group 的工作原理是在组件的生命周期中插入额外的状态。例如,对于 CSSTransition:
当组件进入时,它会经历 'enter' → 'enter-active' → 'enter-done' 状态。 当组件离开时,它会经历 'exit' → 'exit-active' → 'exit-done' 状态。 这些状态会被添加为 CSS 类,你可以为这些类定义样式来控制过渡效果。
通过这种方式,react-transition-group 提供了一个声明式的 API 来处理 React 组件的动画,使得添加复杂的进入和离开动画变得简单。