文档

文档

React

AnimatePresence

AnimatePresence

AnimatePresence 使退出动画变得简单。通过包裹一个或多个 motion组件使用 AnimatePresence,我们可以访问 exit 动画属性。

<AnimatePresence>
  {show && <motion.div key="modal" exit={{ opacity: 0 }} />}
</AnimatePresence>

用法

导入

import { AnimatePresence } from "motion/react"

退出动画

AnimatePresence 通过检测其直接子元素何时从 React 树中移除来工作。

这可能是由于组件挂载/重新挂载

<AnimatePresence>
  {show && <Modal key="modal" />}
</AnimatePresence>

key 更改

<AnimatePresence>
  <Slide key={activeItem.id} />
</AnimatePresence>

或者当列表中的子元素被添加/移除时

<AnimatePresence>
  {items.map(item => (
    <motion.li key={item.id} exit={{ opacity: 1 }} layout />
  ))}
</AnimatePresence>

退出组件中的任何 motion 组件都将触发在其 exit 属性上定义的动画,然后在组件从 DOM 中移除之前执行。

function Slide({ img, description }) {
  return (
    <motion.div exit={{ opacity: 0 }}>
      <img src={img.src} />
      <motion.p exit={{ y: 10 }}>{description}</motion.p>
    </motion.div>
  )
}

注意:直接子元素必须各自具有唯一的 key 属性,以便 AnimatePresence 可以跟踪它们在树中的存在。

initialanimate 一样,exit 可以定义为值对象,也可以定义为变体标签。

const modalVariants = {
  visible: { opacity: 1, transition: { when: "beforeChildren" } },
  hidden: { opacity: 0, transition: { when: "afterChildren" } }
}

function Modal({ children }) {
  return (
    <motion.div initial="hidden" animate="visible" exit="hidden">
      {children}
    </motion.div>
  )
}

更改 key

更改 key 属性使 React 创建一个全新的组件。因此,通过更改 AnimatePresence 的单个子元素的 key,我们可以轻松制作像幻灯片一样的组件。

export const Slideshow = ({ image }) => (
  <AnimatePresence>
    <motion.img
      key={image.src}
      src={image.src}
      initial={{ x: 300, opacity: 0 }}
      animate={{ x: 0, opacity: 1 }}
      exit={{ x: -300, opacity: 0 }}
    />
  </AnimatePresence>
)

访问 presence 状态

AnimatePresence 的任何子元素都可以使用 useIsPresence hook 访问 presence 状态。

import { useIsPresent } from "motion/react"

function Component() {
  const isPresent = useIsPresent()

  return isPresent ? "Here!" : "Exiting..."
}

这允许您在组件不再渲染时更改内容或样式。

访问 presence 数据

当组件已从 React 树中移除时,其 props 将无法再更新。我们可以使用 AnimatePresencecustom 属性将新数据向下传递到树中,甚至传递到退出的组件中。

<AnimatePresence custom={swipeDirection}>
  <Slide key={activeSlideId}>

然后稍后我们可以使用 usePresenceData 提取该数据。

import { AnimatePresence, usePresenceData } from "motion/react"

function Slide() {
  const isPresent = useIsPresent()
  const direction = usePresenceData()

  return (
    <motion.div exit={{ opacity: 0 }}>
      {isPresent ? "Here!" : "Exiting " + direction}
    </motion.div>
  )
}

手动用法

也可以手动告知 AnimatePresence 何时可以使用 usePresence hook 安全地移除组件。

这会返回 isPresent 状态和一个回调 safeToRemove,当您准备好从 DOM 中移除组件时(例如在手动动画或其他超时后),应调用该回调。

import { usePresence } from "motion/react"

function Component() {
  const [isPresent, safeToRemove] = usePresence()

  useEffect(() => {
    // Remove from DOM 1000ms after being removed from React
    !isPresent && setTimeout(safeToRemove, 1000)
  }, [isPresent])

  return <div />
}

传播退出动画

默认情况下,AnimatePresence 控制其所有子元素的 exit 动画,直到渲染另一个 AnimatePresence 组件。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence>
        {/*
          * When `show` becomes `false`, exit animations
          * on these children will not fire.
          */}
        {children}
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

通过将 AnimatePresence 组件的 propagate 属性设置为 true,当它从另一个 AnimatePresence 中移除时,它将触发所有子元素的退出动画。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence propagate>
        {/*
          * When `show` becomes `false`, exit animations
          * on these children **will** fire.
          */}
        {children}
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

属性

initial

通过传递 initial={false}AnimatePresence 将禁用组件首次渲染时存在的子元素的任何初始动画。

<AnimatePresence initial={false}>
  <Slide key={activeItem.id} />
</AnimatePresence>

custom

当组件被移除时,不再有机会更新其 props(因为它不再在 React 树中)。因此,我们无法使用移除组件的相同渲染来更新其退出动画。

通过 AnimatePresencecustom 属性传递一个值,我们可以使用动态变体来更改 exit 动画。

const variants = {
  hidden: (direction) => ({
    opacity: 0,
    x: direction === 1 ? -300 : 300
  }),
  visible: { opacity: 1, x: 0 }
}

export const Slideshow = ({ image, direction }) => (
  <AnimatePresence custom={direction}>
    <motion.img
      key={image.src}
      src={image.src}
      variants={variants}
      initial="hidden"
      animate="visible"
      exit="hidden"
    />
  </AnimatePresence>
)

子元素可以通过 usePresenceData 访问此数据。

mode

默认值:"sync"

决定 AnimatePresence 如何处理进入和退出的子元素。

  • "sync":子元素在添加/移除后立即进行动画进入/退出。

  • "wait":进入的子元素将等待直到退出的子元素动画退出。注意:目前一次只渲染一个子元素。

  • "popLayout":退出的子元素将从页面布局中“弹出”。这允许周围的元素立即移动到它们的新布局。

自定义组件注意:当使用 popLayout 模式时,AnimatePresence 的任何直接子元素,如果是一个自定义组件,必须被 React 的 forwardRef 函数包裹,并将提供的 ref 转发到您希望从布局中弹出的 DOM 节点。

onExitComplete

当所有退出的节点都完成动画退出后触发。

propagate

默认值: false

如果设置为 true,则当此 AnimatePresence 从父级 AnimatePresence 退出时,也会触发子元素的退出动画。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence propagate>
        {/* This exit prop will now fire when show is false */}
        <motion.div exit={{ x: -100 }} />
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

故障排除

退出动画不工作

确保所有直接子元素都获得唯一的 key 属性,该属性在每次渲染中对于该组件保持不变

例如,将 index 作为 key 提供是不好的,因为如果项目重新排序,则 index 将不会与 item 匹配

<AnimatePresence>
  {items.map((item, index) => (
    <Component key={index} />
  ))}
</AnimatePresence>

最好传递对该项目唯一的内容,例如 ID

<AnimatePresence>
  {items.map((item) => (
    <Component key={item.id} />
  ))}
</AnimatePresence>

还要确保 AnimatePresence 位于取消挂载元素的代码之外。如果 AnimatePresence 自身被取消挂载,那么它就无法控制退出动画!

例如,这将不起作用

isVisible && (
  <AnimatePresence>
    <Component />
  </AnimatePresence>
)

相反,条件应该位于 AnimatePresence 的根部

<AnimatePresence>
  {isVisible && <Component />}
</AnimatePresence>

布局动画在 mode="sync" 下不工作

当混合布局和退出动画时,可能需要将组包裹在 LayoutGroup 中,以确保 AnimatePresence 之外的组件知道何时执行布局动画。

<LayoutGroup>
  <motion.ul layout>
    <AnimatePresence>
      {items.map(item => (
        <motion.li layout key={item.id} />
      ))}
    </AnimatePresence>
  </motion.ul>
</LayoutGroup>

布局动画在 mode="popLayout" 下不工作

当任何 HTML 元素具有活动的 transform 时,它会暂时成为偏移父元素其子元素。这可能会导致具有 position: "absolute" 的子元素未出现在您期望的位置。

mode="popLayout" 通过使用 position: "absolute" 工作。因此,为了确保布局动画期间的一致且预期的定位,请确保动画父元素具有除 "static" 之外的 position

<motion.ul layout style={{ position: "relative" }}>
  <AnimatePresence mode="popLayout">
    {items.map(item => (
      <motion.li layout key={item.id} />
    ))}
  </AnimatePresence>
</motion.ul>

AnimatePresence 使退出动画变得简单。通过包裹一个或多个 motion组件使用 AnimatePresence,我们可以访问 exit 动画属性。

<AnimatePresence>
  {show && <motion.div key="modal" exit={{ opacity: 0 }} />}
</AnimatePresence>

用法

导入

import { AnimatePresence } from "motion/react"

退出动画

AnimatePresence 通过检测其直接子元素何时从 React 树中移除来工作。

这可能是由于组件挂载/重新挂载

<AnimatePresence>
  {show && <Modal key="modal" />}
</AnimatePresence>

key 更改

<AnimatePresence>
  <Slide key={activeItem.id} />
</AnimatePresence>

或者当列表中的子元素被添加/移除时

<AnimatePresence>
  {items.map(item => (
    <motion.li key={item.id} exit={{ opacity: 1 }} layout />
  ))}
</AnimatePresence>

退出组件中的任何 motion 组件都将触发在其 exit 属性上定义的动画,然后在组件从 DOM 中移除之前执行。

function Slide({ img, description }) {
  return (
    <motion.div exit={{ opacity: 0 }}>
      <img src={img.src} />
      <motion.p exit={{ y: 10 }}>{description}</motion.p>
    </motion.div>
  )
}

注意:直接子元素必须各自具有唯一的 key 属性,以便 AnimatePresence 可以跟踪它们在树中的存在。

initialanimate 一样,exit 可以定义为值对象,也可以定义为变体标签。

const modalVariants = {
  visible: { opacity: 1, transition: { when: "beforeChildren" } },
  hidden: { opacity: 0, transition: { when: "afterChildren" } }
}

function Modal({ children }) {
  return (
    <motion.div initial="hidden" animate="visible" exit="hidden">
      {children}
    </motion.div>
  )
}

更改 key

更改 key 属性使 React 创建一个全新的组件。因此,通过更改 AnimatePresence 的单个子元素的 key,我们可以轻松制作像幻灯片一样的组件。

export const Slideshow = ({ image }) => (
  <AnimatePresence>
    <motion.img
      key={image.src}
      src={image.src}
      initial={{ x: 300, opacity: 0 }}
      animate={{ x: 0, opacity: 1 }}
      exit={{ x: -300, opacity: 0 }}
    />
  </AnimatePresence>
)

访问 presence 状态

AnimatePresence 的任何子元素都可以使用 useIsPresence hook 访问 presence 状态。

import { useIsPresent } from "motion/react"

function Component() {
  const isPresent = useIsPresent()

  return isPresent ? "Here!" : "Exiting..."
}

这允许您在组件不再渲染时更改内容或样式。

访问 presence 数据

当组件已从 React 树中移除时,其 props 将无法再更新。我们可以使用 AnimatePresencecustom 属性将新数据向下传递到树中,甚至传递到退出的组件中。

<AnimatePresence custom={swipeDirection}>
  <Slide key={activeSlideId}>

然后稍后我们可以使用 usePresenceData 提取该数据。

import { AnimatePresence, usePresenceData } from "motion/react"

function Slide() {
  const isPresent = useIsPresent()
  const direction = usePresenceData()

  return (
    <motion.div exit={{ opacity: 0 }}>
      {isPresent ? "Here!" : "Exiting " + direction}
    </motion.div>
  )
}

手动用法

也可以手动告知 AnimatePresence 何时可以使用 usePresence hook 安全地移除组件。

这会返回 isPresent 状态和一个回调 safeToRemove,当您准备好从 DOM 中移除组件时(例如在手动动画或其他超时后),应调用该回调。

import { usePresence } from "motion/react"

function Component() {
  const [isPresent, safeToRemove] = usePresence()

  useEffect(() => {
    // Remove from DOM 1000ms after being removed from React
    !isPresent && setTimeout(safeToRemove, 1000)
  }, [isPresent])

  return <div />
}

传播退出动画

默认情况下,AnimatePresence 控制其所有子元素的 exit 动画,直到渲染另一个 AnimatePresence 组件。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence>
        {/*
          * When `show` becomes `false`, exit animations
          * on these children will not fire.
          */}
        {children}
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

通过将 AnimatePresence 组件的 propagate 属性设置为 true,当它从另一个 AnimatePresence 中移除时,它将触发所有子元素的退出动画。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence propagate>
        {/*
          * When `show` becomes `false`, exit animations
          * on these children **will** fire.
          */}
        {children}
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

属性

initial

通过传递 initial={false}AnimatePresence 将禁用组件首次渲染时存在的子元素的任何初始动画。

<AnimatePresence initial={false}>
  <Slide key={activeItem.id} />
</AnimatePresence>

custom

当组件被移除时,不再有机会更新其 props(因为它不再在 React 树中)。因此,我们无法使用移除组件的相同渲染来更新其退出动画。

通过 AnimatePresencecustom 属性传递一个值,我们可以使用动态变体来更改 exit 动画。

const variants = {
  hidden: (direction) => ({
    opacity: 0,
    x: direction === 1 ? -300 : 300
  }),
  visible: { opacity: 1, x: 0 }
}

export const Slideshow = ({ image, direction }) => (
  <AnimatePresence custom={direction}>
    <motion.img
      key={image.src}
      src={image.src}
      variants={variants}
      initial="hidden"
      animate="visible"
      exit="hidden"
    />
  </AnimatePresence>
)

子元素可以通过 usePresenceData 访问此数据。

mode

默认值:"sync"

决定 AnimatePresence 如何处理进入和退出的子元素。

  • "sync":子元素在添加/移除后立即进行动画进入/退出。

  • "wait":进入的子元素将等待直到退出的子元素动画退出。注意:目前一次只渲染一个子元素。

  • "popLayout":退出的子元素将从页面布局中“弹出”。这允许周围的元素立即移动到它们的新布局。

自定义组件注意:当使用 popLayout 模式时,AnimatePresence 的任何直接子元素,如果是一个自定义组件,必须被 React 的 forwardRef 函数包裹,并将提供的 ref 转发到您希望从布局中弹出的 DOM 节点。

onExitComplete

当所有退出的节点都完成动画退出后触发。

propagate

默认值: false

如果设置为 true,则当此 AnimatePresence 从父级 AnimatePresence 退出时,也会触发子元素的退出动画。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence propagate>
        {/* This exit prop will now fire when show is false */}
        <motion.div exit={{ x: -100 }} />
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

故障排除

退出动画不工作

确保所有直接子元素都获得唯一的 key 属性,该属性在每次渲染中对于该组件保持不变

例如,将 index 作为 key 提供是不好的,因为如果项目重新排序,则 index 将不会与 item 匹配

<AnimatePresence>
  {items.map((item, index) => (
    <Component key={index} />
  ))}
</AnimatePresence>

最好传递对该项目唯一的内容,例如 ID

<AnimatePresence>
  {items.map((item) => (
    <Component key={item.id} />
  ))}
</AnimatePresence>

还要确保 AnimatePresence 位于取消挂载元素的代码之外。如果 AnimatePresence 自身被取消挂载,那么它就无法控制退出动画!

例如,这将不起作用

isVisible && (
  <AnimatePresence>
    <Component />
  </AnimatePresence>
)

相反,条件应该位于 AnimatePresence 的根部

<AnimatePresence>
  {isVisible && <Component />}
</AnimatePresence>

布局动画在 mode="sync" 下不工作

当混合布局和退出动画时,可能需要将组包裹在 LayoutGroup 中,以确保 AnimatePresence 之外的组件知道何时执行布局动画。

<LayoutGroup>
  <motion.ul layout>
    <AnimatePresence>
      {items.map(item => (
        <motion.li layout key={item.id} />
      ))}
    </AnimatePresence>
  </motion.ul>
</LayoutGroup>

布局动画在 mode="popLayout" 下不工作

当任何 HTML 元素具有活动的 transform 时,它会暂时成为偏移父元素其子元素。这可能会导致具有 position: "absolute" 的子元素未出现在您期望的位置。

mode="popLayout" 通过使用 position: "absolute" 工作。因此,为了确保布局动画期间的一致且预期的定位,请确保动画父元素具有除 "static" 之外的 position

<motion.ul layout style={{ position: "relative" }}>
  <AnimatePresence mode="popLayout">
    {items.map(item => (
      <motion.li layout key={item.id} />
    ))}
  </AnimatePresence>
</motion.ul>

AnimatePresence 使退出动画变得简单。通过包裹一个或多个 motion组件使用 AnimatePresence,我们可以访问 exit 动画属性。

<AnimatePresence>
  {show && <motion.div key="modal" exit={{ opacity: 0 }} />}
</AnimatePresence>

用法

导入

import { AnimatePresence } from "motion/react"

退出动画

AnimatePresence 通过检测其直接子元素何时从 React 树中移除来工作。

这可能是由于组件挂载/重新挂载

<AnimatePresence>
  {show && <Modal key="modal" />}
</AnimatePresence>

key 更改

<AnimatePresence>
  <Slide key={activeItem.id} />
</AnimatePresence>

或者当列表中的子元素被添加/移除时

<AnimatePresence>
  {items.map(item => (
    <motion.li key={item.id} exit={{ opacity: 1 }} layout />
  ))}
</AnimatePresence>

退出组件中的任何 motion 组件都将触发在其 exit 属性上定义的动画,然后在组件从 DOM 中移除之前执行。

function Slide({ img, description }) {
  return (
    <motion.div exit={{ opacity: 0 }}>
      <img src={img.src} />
      <motion.p exit={{ y: 10 }}>{description}</motion.p>
    </motion.div>
  )
}

注意:直接子元素必须各自具有唯一的 key 属性,以便 AnimatePresence 可以跟踪它们在树中的存在。

initialanimate 一样,exit 可以定义为值对象,也可以定义为变体标签。

const modalVariants = {
  visible: { opacity: 1, transition: { when: "beforeChildren" } },
  hidden: { opacity: 0, transition: { when: "afterChildren" } }
}

function Modal({ children }) {
  return (
    <motion.div initial="hidden" animate="visible" exit="hidden">
      {children}
    </motion.div>
  )
}

更改 key

更改 key 属性使 React 创建一个全新的组件。因此,通过更改 AnimatePresence 的单个子元素的 key,我们可以轻松制作像幻灯片一样的组件。

export const Slideshow = ({ image }) => (
  <AnimatePresence>
    <motion.img
      key={image.src}
      src={image.src}
      initial={{ x: 300, opacity: 0 }}
      animate={{ x: 0, opacity: 1 }}
      exit={{ x: -300, opacity: 0 }}
    />
  </AnimatePresence>
)

访问 presence 状态

AnimatePresence 的任何子元素都可以使用 useIsPresence hook 访问 presence 状态。

import { useIsPresent } from "motion/react"

function Component() {
  const isPresent = useIsPresent()

  return isPresent ? "Here!" : "Exiting..."
}

这允许您在组件不再渲染时更改内容或样式。

访问 presence 数据

当组件已从 React 树中移除时,其 props 将无法再更新。我们可以使用 AnimatePresencecustom 属性将新数据向下传递到树中,甚至传递到退出的组件中。

<AnimatePresence custom={swipeDirection}>
  <Slide key={activeSlideId}>

然后稍后我们可以使用 usePresenceData 提取该数据。

import { AnimatePresence, usePresenceData } from "motion/react"

function Slide() {
  const isPresent = useIsPresent()
  const direction = usePresenceData()

  return (
    <motion.div exit={{ opacity: 0 }}>
      {isPresent ? "Here!" : "Exiting " + direction}
    </motion.div>
  )
}

手动用法

也可以手动告知 AnimatePresence 何时可以使用 usePresence hook 安全地移除组件。

这会返回 isPresent 状态和一个回调 safeToRemove,当您准备好从 DOM 中移除组件时(例如在手动动画或其他超时后),应调用该回调。

import { usePresence } from "motion/react"

function Component() {
  const [isPresent, safeToRemove] = usePresence()

  useEffect(() => {
    // Remove from DOM 1000ms after being removed from React
    !isPresent && setTimeout(safeToRemove, 1000)
  }, [isPresent])

  return <div />
}

传播退出动画

默认情况下,AnimatePresence 控制其所有子元素的 exit 动画,直到渲染另一个 AnimatePresence 组件。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence>
        {/*
          * When `show` becomes `false`, exit animations
          * on these children will not fire.
          */}
        {children}
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

通过将 AnimatePresence 组件的 propagate 属性设置为 true,当它从另一个 AnimatePresence 中移除时,它将触发所有子元素的退出动画。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence propagate>
        {/*
          * When `show` becomes `false`, exit animations
          * on these children **will** fire.
          */}
        {children}
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

属性

initial

通过传递 initial={false}AnimatePresence 将禁用组件首次渲染时存在的子元素的任何初始动画。

<AnimatePresence initial={false}>
  <Slide key={activeItem.id} />
</AnimatePresence>

custom

当组件被移除时,不再有机会更新其 props(因为它不再在 React 树中)。因此,我们无法使用移除组件的相同渲染来更新其退出动画。

通过 AnimatePresencecustom 属性传递一个值,我们可以使用动态变体来更改 exit 动画。

const variants = {
  hidden: (direction) => ({
    opacity: 0,
    x: direction === 1 ? -300 : 300
  }),
  visible: { opacity: 1, x: 0 }
}

export const Slideshow = ({ image, direction }) => (
  <AnimatePresence custom={direction}>
    <motion.img
      key={image.src}
      src={image.src}
      variants={variants}
      initial="hidden"
      animate="visible"
      exit="hidden"
    />
  </AnimatePresence>
)

子元素可以通过 usePresenceData 访问此数据。

mode

默认值:"sync"

决定 AnimatePresence 如何处理进入和退出的子元素。

  • "sync":子元素在添加/移除后立即进行动画进入/退出。

  • "wait":进入的子元素将等待直到退出的子元素动画退出。注意:目前一次只渲染一个子元素。

  • "popLayout":退出的子元素将从页面布局中“弹出”。这允许周围的元素立即移动到它们的新布局。

自定义组件注意:当使用 popLayout 模式时,AnimatePresence 的任何直接子元素,如果是一个自定义组件,必须被 React 的 forwardRef 函数包裹,并将提供的 ref 转发到您希望从布局中弹出的 DOM 节点。

onExitComplete

当所有退出的节点都完成动画退出后触发。

propagate

默认值: false

如果设置为 true,则当此 AnimatePresence 从父级 AnimatePresence 退出时,也会触发子元素的退出动画。

<AnimatePresence>
  {show ? (
    <motion.section exit={{ opacity: 0 }}>
      <AnimatePresence propagate>
        {/* This exit prop will now fire when show is false */}
        <motion.div exit={{ x: -100 }} />
      </AnimatePresence>
    </motion.section>
  ) : null}
</AnimatePresence>

故障排除

退出动画不工作

确保所有直接子元素都获得唯一的 key 属性,该属性在每次渲染中对于该组件保持不变

例如,将 index 作为 key 提供是不好的,因为如果项目重新排序,则 index 将不会与 item 匹配

<AnimatePresence>
  {items.map((item, index) => (
    <Component key={index} />
  ))}
</AnimatePresence>

最好传递对该项目唯一的内容,例如 ID

<AnimatePresence>
  {items.map((item) => (
    <Component key={item.id} />
  ))}
</AnimatePresence>

还要确保 AnimatePresence 位于取消挂载元素的代码之外。如果 AnimatePresence 自身被取消挂载,那么它就无法控制退出动画!

例如,这将不起作用

isVisible && (
  <AnimatePresence>
    <Component />
  </AnimatePresence>
)

相反,条件应该位于 AnimatePresence 的根部

<AnimatePresence>
  {isVisible && <Component />}
</AnimatePresence>

布局动画在 mode="sync" 下不工作

当混合布局和退出动画时,可能需要将组包裹在 LayoutGroup 中,以确保 AnimatePresence 之外的组件知道何时执行布局动画。

<LayoutGroup>
  <motion.ul layout>
    <AnimatePresence>
      {items.map(item => (
        <motion.li layout key={item.id} />
      ))}
    </AnimatePresence>
  </motion.ul>
</LayoutGroup>

布局动画在 mode="popLayout" 下不工作

当任何 HTML 元素具有活动的 transform 时,它会暂时成为偏移父元素其子元素。这可能会导致具有 position: "absolute" 的子元素未出现在您期望的位置。

mode="popLayout" 通过使用 position: "absolute" 工作。因此,为了确保布局动画期间的一致且预期的定位,请确保动画父元素具有除 "static" 之外的 position

<motion.ul layout style={{ position: "relative" }}>
  <AnimatePresence mode="popLayout">
    {items.map(item => (
      <motion.li layout key={item.id} />
    ))}
  </AnimatePresence>
</motion.ul>

AnimatePresence

示例

超越基础

Motion+是一次性付费,终身会员资格。

除了高级 Motion 功能、抢先体验内容和私人 Discord 社区外,您还将解锁访问 90 多个高级示例的源代码的权限,这些示例将此页面上的 API 提升到一个新的水平。

加载中...
加载中...
保持关注

订阅以获取最新消息和更新。

保持关注

订阅以获取最新消息和更新。