持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
用法可以参考这个:www.jianshu.com/p/49fa164b9…
其实和第一章的类似
文档:reactcommunity.org/react-trans…
它建立在 Transition 组件之上,因此它继承了它的所有 props。
CSSTransition 在过渡的出现、进入和退出状态期间应用一对类名。
The animation classNames applied to the component as it appears, enters, exits or has finished the transition. A single name can be provided, which will be suffixed for each stage, e.g. classNames="fade" applies:
在组件出现、进入、退出或完成过渡时应用于组件的动画类名。可以提供一个名称,每个阶段都会加上后缀,例如classNames="fade" 适用
fade-appear,fade-appear-active,fade-appear-donefade-enter,fade-enter-active,fade-enter-donefade-exit,fade-exit-active,fade-exit-done
例子
import { useState } from "react";
import "./App.css";
import "./test.css";
import { CSSTransition } from "react-transition-group";
const duration = 1030;
// 动画 样式
function App() {
const [inProp, setInProp] = useState(false);
return (
<div className="App">
<header className="App-header">
{/* in 显示组件;触发进入或退出状态,默认false。 timeout 动画时间 */}
<CSSTransition in={inProp} timeout={duration} classNames="fade"
onEnter={() => console.log("onEnter")}>
{(state) => <div>I'm a fade Transition!</div>}
</CSSTransition>
<button onClick={() => setInProp(!inProp)}>Click to Enter</button>
</header>
</div>
);
}
export default App;
# test.css
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.fade-enter-done {
opacity: 1;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 200ms;
}
.fade-exit-done {
opacity: 0;
}
初始的时候没有类,in为true后,赋予了fade-enter和fade-enter-active,动画时间后变成fade-enter-done。
由true变false,enter变成exit。
动画的状态就是从fade-enter变成fade-enter-active。
还有六个属性
onEnter
onEntering
onEntered
onExit
onExiting
onExited
onEnter:A <Transition> callback fired immediately after the 'enter' or 'appear' class is applied.
Note: when nodeRef prop is passed, node is not passed.
type: Function(node: HtmlElement, isAppearing: bool)
原理:
当元素进入动画时 调用 该回调,参数的元素。
调用
onEnter时,要去掉exit相关的类,添加enter类。调用
onEntering,添加entering调用
onEntered,去掉 前面两个类,添加onEntered
源码实现
- 该组件是在
Transition基础上实现的,先继承过来
import {Transition} from './Transition';
function CSSTransition(props) {
// 获取动画类名
function getClassNames(status) {
const { classNames } = props;
return {
// fade-enter, fade-enter-active, fade-enter-done
base: `${classNames}-${status}`, // 基础样式
active: `${classNames}-${status}-active`,//动画样式
done: `${classNames}-${status}-done`
}
}
function onEnter(node) {
// 获取动画结束的类,并去掉,添加动画开始的类名
const exitClassNames = Object.values(getClassNames("exit")); // ['fade-exit', 'fade-exit-active', 'fade-exit-done']
removeClass(node, exitClassNames);
const enterClassName = getClassNames("enter").base; // ['fade-enter', 'fade-enter-active', 'fade-enter-done']
addClass(node, enterClassName);
props?.onEnter(node); // 回调函数
}
return (
<Transition onEnter={onEnter} in={props.in} timeout={props.timeout}>
{props.children}
</Transition>
)
}
function removeClass(node, classes) {
// 移除样式
(Array.isArray(classes) ? classes : [classes]).forEach((cls) =>
node.classList.remove(cls)
);
}
// 添加样式
function addClass(node, classes) {
(Array.isArray(classes) ? classes : [classes]).forEach((cls) =>
node.classList.add(cls)
);
}
export { CSSTransition }
- 在
Transition里 完成onEnter等属性的插入
performEnter = () => {
const { timeout, onEnter, onEntering, onEntered } = this.props
const node = ReactDom.findDOMNode(this)
onEnter?.(node)
this.setState({
status: ENTERING
}, () => {
onEntering?.(node)
this.onTransitionEnd(timeout, () => {
this.setState({ status: ENTERED })
onEntered?.(node)
})
})
}
完整源码
import { Transition } from "./Transition";
function CSSTransition(props) {
// 获取动画类名
function getClassNames(status) {
const { classNames } = props;
return {
// fade-enter, fade-enter-active, fade-enter-done
base: `${classNames}-${status}`, // 基础样式
active: `${classNames}-${status}-active`, //动画样式
done: `${classNames}-${status}-done`,
};
}
function onEnter(node) {
// 获取动画结束的类,并去掉,添加动画开始的类名
const exitClassNames = Object.values(getClassNames("exit")); // ['fade-exit', 'fade-exit-active', 'fade-exit-done']
removeClass(node, exitClassNames);
const enterClassName = getClassNames("enter").base; // ['fade-enter', 'fade-enter-active', 'fade-enter-done']
addClass(node, enterClassName);
props?.onEnter(node); // 回调函数
}
function onEntering(node) {
const enterClassName = getClassNames("enter").active; // ['fade-enter', 'fade-enter-active', 'fade-enter-done']
addClass(node, enterClassName);
}
function onEntered(node) {
const { base, active, done } = getClassNames("enter");
removeClass(node, [base, active]);
addClass(node, done);
}
function onExit(node) {
// 获取动画结束的类,并去掉,添加动画开始的类名
const exitClassNames = Object.values(getClassNames("enter")); // ['fade-exit', 'fade-exit-active', 'fade-exit-done']
removeClass(node, exitClassNames);
const enterClassName = getClassNames("exit").base; // ['fade-enter', 'fade-enter-active', 'fade-enter-done']
addClass(node, enterClassName);
}
function onExiting(node) {
const enterClassName = getClassNames("exit").active; // ['fade-enter', 'fade-enter-active', 'fade-enter-done']
addClass(node, enterClassName);
}
function onExited(node) {
const { base, active, done } = getClassNames("exit");
removeClass(node, [base, active]);
addClass(node, done);
}
return (
<Transition
onEnter={onEnter}
onEntering={onEntering}
onEntered={onEntered}
onExit={onExit}
onExiting={onExiting}
onExited={onExited}
in={props.in}
timeout={props.timeout}
>
{props.children}
</Transition>
);
}
function removeClass(node, classes) {
// 移除样式
(Array.isArray(classes) ? classes : [classes]).forEach((cls) =>
node.classList.remove(cls)
);
}
// 添加样式
function addClass(node, classes) {
(Array.isArray(classes) ? classes : [classes]).forEach((cls) =>
node.classList.add(cls)
);
}
export { CSSTransition };