输入时动画不起作用(Tailwind、TransitionGroup、Typescript)
Animations not working when entering (Tailwind, TransitionGroup, Typescript)
我创建了一个包装器组件,通过字符串提供 class 名称列表,以支持 Tailwind 实用程序转换。这旨在嵌套在 TransitionGroup 组件中以支持多个项目的动画,如列表。
我可以很好地制作出动画,但无法进入。你能帮我找出这段代码中的错误吗?
反应 16.13.1
反应过渡组 4.4.1
沙盒:https://codesandbox.io/s/delicate-feather-ymozq
(登录那里观看 div 参考,以防 classes 没有被应用,但它们似乎工作正常)
import React, { ReactNode } from "react";
import { Transition as ReactTransition } from "react-transition-group";
interface TransitionProps {
in?: boolean;
timeout: number;
enter?: string;
enterFrom?: string;
enterTo?: string;
leave?: string;
leaveFrom?: string;
leaveTo?: string;
children: ReactNode;
}
export function CSSTransition(props: TransitionProps) {
const { enter, enterFrom, enterTo, leave, leaveFrom, leaveTo } = props;
const nodeRef = React.useRef<HTMLDivElement>(null);
const enterClasses = splitClasses(enter);
const enterFromClasses = splitClasses(enterFrom);
const enterToClasses = splitClasses(enterTo);
const leaveClasses = splitClasses(leave);
const leaveFromClasses = splitClasses(leaveFrom);
const leaveToClasses = splitClasses(leaveTo);
function splitClasses(string: string | undefined): string[] {
if (string) return string.split(" ").filter((s) => s.length);
return [];
}
function addClasses(classes: string[]) {
nodeRef.current?.classList.add(...classes);
}
function removeClasses(classes: string[]) {
nodeRef.current?.classList.remove(...classes);
}
return (
<ReactTransition
in={props.in}
nodeRef={nodeRef}
timeout={props.timeout}
unmountOnExit
onEnter={() => {
console.log("onEnter", nodeRef);
addClasses([...enterClasses, ...enterFromClasses]);
}}
onEntering={() => {
console.log("onEntering", nodeRef);
removeClasses(enterFromClasses);
addClasses(enterToClasses);
}}
onEntered={() => {
console.log("onEntered", nodeRef);
removeClasses([...enterToClasses, ...enterClasses]);
}}
onExit={() => {
console.log("onExit", nodeRef);
addClasses([...leaveClasses, ...leaveFromClasses]);
}}
onExiting={() => {
console.log("onExiting", nodeRef);
removeClasses(leaveFromClasses);
addClasses(leaveToClasses);
}}
onExited={() => {
console.log("onExited", nodeRef);
removeClasses([...leaveToClasses, ...leaveClasses]);
}}
>
<div ref={nodeRef}>{props.children}</div>
</ReactTransition>
);
}
解决方案:
在CSSTransition.tsx
中,更改
import { Transition as ReactTransition } from "react-transition-group";
到
import { CSSTransition as ReactTransition } from "react-transition-group";
解释:
Tailwind class 名称依赖于 CSS 动画。
Transition
不适用于 CSS 动画,因为 onEnter
和 onEntering
方法的调用速度如此之快以至于 DOM 重绘(动画的一帧)不会出现在它们之间。因此,您为 enterTo
设置的所有 classes 都会立即应用,没有任何机会过渡到它们。
另一方面,CSS Transition
在创建元素时添加 -enter
class,然后在下一个 -enter-active
=66=]。最后,在超时后,它会删除所有 classes 除了添加 -done
class。
-enter
和 -enter-active
class 之间的过渡是允许 CSS 过渡发生的关键。在那些 class 之间添加一个 tick/frame 允许库强制重绘。此重绘强制 onEntering
classes 按预期过渡到 onEntered
classes。
换句话说,Transition
立即切换到 enterTo
状态,而 CSSTransition
在 class 切换之间提供一帧,这是允许动画进行所需的地方。
DOM通常animates/changes每秒最多60帧(取决于implementation/end-user屏幕刷新率)每帧留出16ms;它不关心这 16 毫秒之间发生了什么。如果 class 更改后的最终状态是您的 enterTo
状态而不是您的 enterFrom
状态,它将忽略 enterFrom
状态,因此永远不会向您显示 Tailwind 动画。
来源:
我创建了一个包装器组件,通过字符串提供 class 名称列表,以支持 Tailwind 实用程序转换。这旨在嵌套在 TransitionGroup 组件中以支持多个项目的动画,如列表。
我可以很好地制作出动画,但无法进入。你能帮我找出这段代码中的错误吗?
反应 16.13.1 反应过渡组 4.4.1
沙盒:https://codesandbox.io/s/delicate-feather-ymozq
(登录那里观看 div 参考,以防 classes 没有被应用,但它们似乎工作正常)
import React, { ReactNode } from "react";
import { Transition as ReactTransition } from "react-transition-group";
interface TransitionProps {
in?: boolean;
timeout: number;
enter?: string;
enterFrom?: string;
enterTo?: string;
leave?: string;
leaveFrom?: string;
leaveTo?: string;
children: ReactNode;
}
export function CSSTransition(props: TransitionProps) {
const { enter, enterFrom, enterTo, leave, leaveFrom, leaveTo } = props;
const nodeRef = React.useRef<HTMLDivElement>(null);
const enterClasses = splitClasses(enter);
const enterFromClasses = splitClasses(enterFrom);
const enterToClasses = splitClasses(enterTo);
const leaveClasses = splitClasses(leave);
const leaveFromClasses = splitClasses(leaveFrom);
const leaveToClasses = splitClasses(leaveTo);
function splitClasses(string: string | undefined): string[] {
if (string) return string.split(" ").filter((s) => s.length);
return [];
}
function addClasses(classes: string[]) {
nodeRef.current?.classList.add(...classes);
}
function removeClasses(classes: string[]) {
nodeRef.current?.classList.remove(...classes);
}
return (
<ReactTransition
in={props.in}
nodeRef={nodeRef}
timeout={props.timeout}
unmountOnExit
onEnter={() => {
console.log("onEnter", nodeRef);
addClasses([...enterClasses, ...enterFromClasses]);
}}
onEntering={() => {
console.log("onEntering", nodeRef);
removeClasses(enterFromClasses);
addClasses(enterToClasses);
}}
onEntered={() => {
console.log("onEntered", nodeRef);
removeClasses([...enterToClasses, ...enterClasses]);
}}
onExit={() => {
console.log("onExit", nodeRef);
addClasses([...leaveClasses, ...leaveFromClasses]);
}}
onExiting={() => {
console.log("onExiting", nodeRef);
removeClasses(leaveFromClasses);
addClasses(leaveToClasses);
}}
onExited={() => {
console.log("onExited", nodeRef);
removeClasses([...leaveToClasses, ...leaveClasses]);
}}
>
<div ref={nodeRef}>{props.children}</div>
</ReactTransition>
);
}
解决方案:
在CSSTransition.tsx
中,更改
import { Transition as ReactTransition } from "react-transition-group";
到
import { CSSTransition as ReactTransition } from "react-transition-group";
解释:
Tailwind class 名称依赖于 CSS 动画。
Transition
不适用于 CSS 动画,因为 onEnter
和 onEntering
方法的调用速度如此之快以至于 DOM 重绘(动画的一帧)不会出现在它们之间。因此,您为 enterTo
设置的所有 classes 都会立即应用,没有任何机会过渡到它们。
CSS Transition
在创建元素时添加 -enter
class,然后在下一个 -enter-active
=66=]。最后,在超时后,它会删除所有 classes 除了添加 -done
class。
-enter
和 -enter-active
class 之间的过渡是允许 CSS 过渡发生的关键。在那些 class 之间添加一个 tick/frame 允许库强制重绘。此重绘强制 onEntering
classes 按预期过渡到 onEntered
classes。
换句话说,Transition
立即切换到 enterTo
状态,而 CSSTransition
在 class 切换之间提供一帧,这是允许动画进行所需的地方。
DOM通常animates/changes每秒最多60帧(取决于implementation/end-user屏幕刷新率)每帧留出16ms;它不关心这 16 毫秒之间发生了什么。如果 class 更改后的最终状态是您的 enterTo
状态而不是您的 enterFrom
状态,它将忽略 enterFrom
状态,因此永远不会向您显示 Tailwind 动画。