安装
yarn add react-transition-group
yarn add @types/react-transition-group
Transition
Transition组件允许你使用简单的声明性API描述随时间从一个组件状态到另一个组件状态的转换。最常见的是,它被用于动画组件的挂载和卸载,但也可以用于描述就地转换状态。
注意:Transition是一个平台无关的基础组件。如果你在CSS中使用过渡,你可能会想要使用CSS过渡。它继承了Transition的所有特性,但包含了其他必要的特性,以更好地处理CSS过渡(因此该组件的名称)。
默认情况下Transition组件不会改变它呈现的组件的行为,它只跟踪组件的“进入”和“退出”状态。这取决于你赋予这些状态意义和效果。例如,当组件进入或退出时,我们可以向它添加样式。
在一个过渡中有四种主要状态:
entering
entered
exiting
exited
过渡状态通过in属性切换。当为true时,组件开始“Enter”阶段。在此阶段中,组件将从当前转换状态转移到转换期间的“进入”状态,然后在完成转换后再转移到“进入”状态。
import { Transition } from 'react-transition-group';
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 },
};
const Fade = ({ in: inProp }) => (
<Transition in={inProp} timeout={duration}>
{state => (
<div style={{
...defaultStyle,
...transitionStyles[state]
}}>
I'm a fade Transition!
</div>
)}
</Transition>
);
CSSTransition
适用场景
单个元素过渡
(1) in 传入boolean值,传入的是true代表开启 enter enter-active和enter-done的这一变化过程,传入false代码开启 exit exit-active exit-done这一过程 (必传)
(2) timeout 表示执行时间,enter-active到enter-done 或者 exit-active到exit-done的执行时间 (必传)
(3) classNames 定义添加的类名,这里定义的类名会被添加到 enter-xxx 及 exit-xxx 的之前
(4) ummountOnExit 默认为false,表示当传入in的值为false值,CSSTransition中的元素会从dom中移除
(5) appear 定义首次加载的动画, 同时需要在css中添加对应的类名和样式, 可以与enter一致
(6) 动画执行还有一些回调方法,需传入函数,函数有一个入参,参数为CSSTransition所包裹的元素
onEnter、onEntering、onEntered、onExit、onExiting、onExited
import React, { useState } from 'react';
import './test.scss';
import { CSSTransition } from 'react-transition-group';
const AppTest: React.FC = () => {
const [isShow, setShow] = useState<boolean>(true);
return (
<div className="simpleTransition">
<button onClick={() => setShow(!isShow)}>当前状态:{isShow ? '显示' : '隐藏'}</button>
<CSSTransition
in={isShow}
classNames="box"
timeout={1000}
unmountOnExit
appear
onEnter={ el=>console.log('开始进入',el)}
onEntering={ el => console.log('正在进入')}
onEntered={ el => console.log('进入完成')}
onExit={ el => console.log('开始退出')}
onExiting={ el => console.log('正在退出')}
onExited={ el => console.log('退出完成')}>
<div className="helloBox">hello</div>
</CSSTransition>
</div>
);
};
export default AppTest;
css部分
情况一:如果不需要首次渲染换句话说元素一开始是隐藏的点击后才出现用下面的css
.box-enter {
opacity: 0;
transform: scale(0.6)
}
.box-enter-active {
opacity: 1;
transform: scale(1);
transition: all 1000ms;
}
.box-exit {
opacity: 1;
transform: scale(1);
}
.box-exit-active {
opacity: 0;
transform: scale(.6);
transition: all 1000ms
}
情况二:如果不需要首次渲染换句话说元素一开始是出现的点击后才隐藏用下面的css
//当isShow位true时首次渲染执行
.box-enter, .box-appear {
opacity: 0;
transform: scale(0.6)
}
.box-enter-active, .box-appear-active {
opacity: 1;
transform: scale(1);
transition: all 1000ms;
}
.box-exit {
opacity: 1;
transform: scale(1);
}
.box-exit-active {
opacity: 0;
transform: scale(.6);
transition: all 1000ms
}
SwitchTransition
适用场景
两个个元素或以上过渡,只限于一个元素进入动画,然后两一个元素再进入动画,如果你希望同时进行请使用TransitionGroup
例如轮播组件的制作
1.两种模式
- mode=“out-in”
- mode=“in-out”
import React, { useState } from 'react';
import './test.scss';
import { CSSTransition, SwitchTransition } from 'react-transition-group';
const AppTest: React.FC = () => {
const [isShow, setShow] = useState<boolean>(true);
return (
<div className="simpleTransition">
<button onClick={() => setShow(!isShow)}>当前状态:{isShow ? '显示' : '隐藏'}</button>
<hr />
<SwitchTransition mode="out-in">
<CSSTransition key={isShow ? 'on' : 'off'} classNames="btn" timeout={1000}>
<button onClick={() => setShow(!isShow)}>{isShow ? 'on' : 'off'}</button>
</CSSTransition>
</SwitchTransition>
</div>
);
};
export default AppTest;
css
.btn-enter {
opacity: 0;
transform: translateX(100%)
}
.btn-enter-active {
opacity: 1;
transform: translateX(0);
transition: opacity 1s, transform 1s
}
.btn-exit {
opacity: 1;
transform: translateX(0)
}
.btn-exit-active {
opacity: 0;
transform: translateX(-100%);
transition: opacity 1s, transform 1s;
}
GroupTransition
适用场景
两个个元素或以上过渡,只限于一个元素进入动画,然后两一个元素再进入动画,如果你希望同时进行请使用TransitionGroup
例如轮播组件的制作
多个元素过渡
import React, { useState } from 'react';
import './test.scss';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
const AppTest: React.FC = () => {
const [items, setItems] = useState([
{ id: 1, text: 'Buy eggs' },
{ id: 2, text: 'Pay bills' },
{ id: 3, text: 'Invite friends over' },
{ id: 4, text: 'Fix the TV' }
]);
return (
<div>
<TransitionGroup>
{items.map(({ id, text }) => (
<CSSTransition key={id} timeout={500} classNames="item">
<div>{text}</div>
</CSSTransition>
))}
</TransitionGroup>
<button
onClick={() => {
setItems((state) => [
...state,
{
id: state.length + 1,
text: Math.random().toString()
}
]);
}}
>
Add Item
</button>
</div>
);
};
export default AppTest;
css
.item{
border: 1px solid red;
}
.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;
}