AnimatePresence
AnimatePresence 让退出动画变得简单。通过包裹一个或多个 motion组件使用 AnimatePresence,我们可以访问 exit 动画属性。
<AnimatePresence> <motion.div v-if="show" key="modal" :exit="{ opacity: 0 }" />} </AnimatePresence>
用法
导入
import { AnimatePresence } from "motion-v"
退出动画
AnimatePresence 通过检测其 直接子元素 何时从 Vue 树中移除来工作。
这可能是由于组件的挂载/重新挂载
<AnimatePresence> <Modal v-if="show" key="modal" /> </AnimatePresence>
或使用 v-show
<AnimatePresence> <Modal v-show="show" key="modal" /> </AnimatePresence>
或其 key 更改
<AnimatePresence> <Slide :key="activeItem.id" /> </AnimatePresence>
或当列表中的子元素被添加/移除时
<AnimatePresence> <motion.li v-for="item in items" :key="item.id" :exit="{ opacity: 1 }" layout /> </AnimatePresence>
退出组件中的任何 motion 组件都将在组件从 DOM 中移除之前触发在其 exit 属性上定义的动画。
<template> <motion.div :exit="{ opacity: 0 }"> <img :src="img.src" /> <motion.p :exit="{ y: 10 }">{{description}}</motion.p> </motion.div> </template>
注意:直接子元素必须各自具有唯一的 key 属性,以便 AnimatePresence 可以跟踪它们在树中的存在。
与 initial 和 animate 类似,exit 可以定义为值对象或变体标签。
<script setup> const modalVariants = { visible: { opacity: 1, transition: { when: "beforeChildren" } }, hidden: { opacity: 0, transition: { when: "afterChildren" } } } </script> <template> <motion.div :variants="modalVariants" initial="hidden" animate="visible" exit="hidden" > {{children}} </motion.div> </template>
更改 key
更改 key 属性使 Vue 创建一个全新的组件。因此,通过更改 AnimatePresence 的单个子元素的 key,我们可以轻松制作像幻灯片这样的组件。
<template> <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> </template>
属性
initial
通过传递 :initial="false",AnimatePresence 将禁用组件首次渲染时存在的子元素的任何初始动画。
<AnimatePresence :initial="false"> <Slide :key="activeItem.id" /> </AnimatePresence>
custom
当组件被移除时,不再有机会更新其属性(因为它不再在 Vue 树中)。因此,我们无法使用移除组件的相同渲染来更新其退出动画。
通过 AnimatePresence 的 custom 属性传递值,我们可以使用动态变体来更改 exit 动画。
<script setup> const variants = { hidden: (direction) => ({ opacity: 0, x: direction === 1 ? -300 : 300 }), visible: { opacity: 1, x: 0 } } </script> <template> <AnimatePresence :custom="direction"> <motion.img :key="image.src" :src="image.src" :variants="variants" initial="hidden" animate="visible" exit="hidden" /> </AnimatePresence> </template>
mode
默认值:"sync"
决定 AnimatePresence 如何处理进入和退出的子元素。
"sync":子元素在添加/移除后立即进行动画。"wait":进入的子元素将等待直到退出的子元素动画退出。注意:目前一次只渲染一个子元素。"popLayout":退出的子元素将从页面布局中“弹出”。这允许周围的元素立即移动到它们的新布局。
onExitComplete
当所有退出的节点完成动画退出时触发。
故障排除
退出动画不起作用
确保所有直接子元素都获得一个唯一的 key 属性,该属性对于每个渲染的组件保持不变。
例如,将 index 作为 key 是 不好的,因为如果项目重新排序,则 index 将不会与 item 匹配
<AnimatePresence> <Component v-for="(item,index) in items" :key="index" /> </AnimatePresence>
最好传递对该项目唯一的东西,例如 ID
<AnimatePresence> <Componen v-for="(item,index) in items" :key="item.id" /> </AnimatePresence>
还要确保 AnimatePresence 位于取消挂载元素的代码的外部。如果 AnimatePresence 自身被取消挂载,则它无法控制退出动画!
例如,这会 不起作用
<AnimatePresence v-if="isVisible"> <Component /> </AnimatePresence>
相反,条件应该位于 AnimatePresence 的根部
<AnimatePresence> <Component v-if="isVisible" /> </AnimatePresence>
布局动画在 mode="sync" 下不起作用
当混合布局和退出动画时,可能需要将组包裹在 LayoutGroup 中,以确保 AnimatePresence 外部的组件知道何时执行布局动画。
<LayoutGroup> <motion.ul layout> <AnimatePresence> <motion.li v-for="item in items" 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"> <motion.li v-for="item in items" layout :key="item.id" /> </AnimatePresence> </motion.ul>
AnimatePresence 让退出动画变得简单。通过包裹一个或多个 motion组件使用 AnimatePresence,我们可以访问 exit 动画属性。
<AnimatePresence> <motion.div v-if="show" key="modal" :exit="{ opacity: 0 }" />} </AnimatePresence>
用法
导入
import { AnimatePresence } from "motion-v"
退出动画
AnimatePresence 通过检测其 直接子元素 何时从 Vue 树中移除来工作。
这可能是由于组件的挂载/重新挂载
<AnimatePresence> <Modal v-if="show" key="modal" /> </AnimatePresence>
或使用 v-show
<AnimatePresence> <Modal v-show="show" key="modal" /> </AnimatePresence>
或其 key 更改
<AnimatePresence> <Slide :key="activeItem.id" /> </AnimatePresence>
或当列表中的子元素被添加/移除时
<AnimatePresence> <motion.li v-for="item in items" :key="item.id" :exit="{ opacity: 1 }" layout /> </AnimatePresence>
退出组件中的任何 motion 组件都将在组件从 DOM 中移除之前触发在其 exit 属性上定义的动画。
<template> <motion.div :exit="{ opacity: 0 }"> <img :src="img.src" /> <motion.p :exit="{ y: 10 }">{{description}}</motion.p> </motion.div> </template>
注意:直接子元素必须各自具有唯一的 key 属性,以便 AnimatePresence 可以跟踪它们在树中的存在。
与 initial 和 animate 类似,exit 可以定义为值对象或变体标签。
<script setup> const modalVariants = { visible: { opacity: 1, transition: { when: "beforeChildren" } }, hidden: { opacity: 0, transition: { when: "afterChildren" } } } </script> <template> <motion.div :variants="modalVariants" initial="hidden" animate="visible" exit="hidden" > {{children}} </motion.div> </template>
更改 key
更改 key 属性使 Vue 创建一个全新的组件。因此,通过更改 AnimatePresence 的单个子元素的 key,我们可以轻松制作像幻灯片这样的组件。
<template> <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> </template>
属性
initial
通过传递 :initial="false",AnimatePresence 将禁用组件首次渲染时存在的子元素的任何初始动画。
<AnimatePresence :initial="false"> <Slide :key="activeItem.id" /> </AnimatePresence>
custom
当组件被移除时,不再有机会更新其属性(因为它不再在 Vue 树中)。因此,我们无法使用移除组件的相同渲染来更新其退出动画。
通过 AnimatePresence 的 custom 属性传递值,我们可以使用动态变体来更改 exit 动画。
<script setup> const variants = { hidden: (direction) => ({ opacity: 0, x: direction === 1 ? -300 : 300 }), visible: { opacity: 1, x: 0 } } </script> <template> <AnimatePresence :custom="direction"> <motion.img :key="image.src" :src="image.src" :variants="variants" initial="hidden" animate="visible" exit="hidden" /> </AnimatePresence> </template>
mode
默认值:"sync"
决定 AnimatePresence 如何处理进入和退出的子元素。
"sync":子元素在添加/移除后立即进行动画。"wait":进入的子元素将等待直到退出的子元素动画退出。注意:目前一次只渲染一个子元素。"popLayout":退出的子元素将从页面布局中“弹出”。这允许周围的元素立即移动到它们的新布局。
onExitComplete
当所有退出的节点完成动画退出时触发。
故障排除
退出动画不起作用
确保所有直接子元素都获得一个唯一的 key 属性,该属性对于每个渲染的组件保持不变。
例如,将 index 作为 key 是 不好的,因为如果项目重新排序,则 index 将不会与 item 匹配
<AnimatePresence> <Component v-for="(item,index) in items" :key="index" /> </AnimatePresence>
最好传递对该项目唯一的东西,例如 ID
<AnimatePresence> <Componen v-for="(item,index) in items" :key="item.id" /> </AnimatePresence>
还要确保 AnimatePresence 位于取消挂载元素的代码的外部。如果 AnimatePresence 自身被取消挂载,则它无法控制退出动画!
例如,这会 不起作用
<AnimatePresence v-if="isVisible"> <Component /> </AnimatePresence>
相反,条件应该位于 AnimatePresence 的根部
<AnimatePresence> <Component v-if="isVisible" /> </AnimatePresence>
布局动画在 mode="sync" 下不起作用
当混合布局和退出动画时,可能需要将组包裹在 LayoutGroup 中,以确保 AnimatePresence 外部的组件知道何时执行布局动画。
<LayoutGroup> <motion.ul layout> <AnimatePresence> <motion.li v-for="item in items" 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"> <motion.li v-for="item in items" layout :key="item.id" /> </AnimatePresence> </motion.ul>
AnimatePresence 让退出动画变得简单。通过包裹一个或多个 motion组件使用 AnimatePresence,我们可以访问 exit 动画属性。
<AnimatePresence> <motion.div v-if="show" key="modal" :exit="{ opacity: 0 }" />} </AnimatePresence>
用法
导入
import { AnimatePresence } from "motion-v"
退出动画
AnimatePresence 通过检测其 直接子元素 何时从 Vue 树中移除来工作。
这可能是由于组件的挂载/重新挂载
<AnimatePresence> <Modal v-if="show" key="modal" /> </AnimatePresence>
或使用 v-show
<AnimatePresence> <Modal v-show="show" key="modal" /> </AnimatePresence>
或其 key 更改
<AnimatePresence> <Slide :key="activeItem.id" /> </AnimatePresence>
或当列表中的子元素被添加/移除时
<AnimatePresence> <motion.li v-for="item in items" :key="item.id" :exit="{ opacity: 1 }" layout /> </AnimatePresence>
退出组件中的任何 motion 组件都将在组件从 DOM 中移除之前触发在其 exit 属性上定义的动画。
<template> <motion.div :exit="{ opacity: 0 }"> <img :src="img.src" /> <motion.p :exit="{ y: 10 }">{{description}}</motion.p> </motion.div> </template>
注意:直接子元素必须各自具有唯一的 key 属性,以便 AnimatePresence 可以跟踪它们在树中的存在。
与 initial 和 animate 类似,exit 可以定义为值对象或变体标签。
<script setup> const modalVariants = { visible: { opacity: 1, transition: { when: "beforeChildren" } }, hidden: { opacity: 0, transition: { when: "afterChildren" } } } </script> <template> <motion.div :variants="modalVariants" initial="hidden" animate="visible" exit="hidden" > {{children}} </motion.div> </template>
更改 key
更改 key 属性使 Vue 创建一个全新的组件。因此,通过更改 AnimatePresence 的单个子元素的 key,我们可以轻松制作像幻灯片这样的组件。
<template> <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> </template>
属性
initial
通过传递 :initial="false",AnimatePresence 将禁用组件首次渲染时存在的子元素的任何初始动画。
<AnimatePresence :initial="false"> <Slide :key="activeItem.id" /> </AnimatePresence>
custom
当组件被移除时,不再有机会更新其属性(因为它不再在 Vue 树中)。因此,我们无法使用移除组件的相同渲染来更新其退出动画。
通过 AnimatePresence 的 custom 属性传递值,我们可以使用动态变体来更改 exit 动画。
<script setup> const variants = { hidden: (direction) => ({ opacity: 0, x: direction === 1 ? -300 : 300 }), visible: { opacity: 1, x: 0 } } </script> <template> <AnimatePresence :custom="direction"> <motion.img :key="image.src" :src="image.src" :variants="variants" initial="hidden" animate="visible" exit="hidden" /> </AnimatePresence> </template>
mode
默认值:"sync"
决定 AnimatePresence 如何处理进入和退出的子元素。
"sync":子元素在添加/移除后立即进行动画。"wait":进入的子元素将等待直到退出的子元素动画退出。注意:目前一次只渲染一个子元素。"popLayout":退出的子元素将从页面布局中“弹出”。这允许周围的元素立即移动到它们的新布局。
onExitComplete
当所有退出的节点完成动画退出时触发。
故障排除
退出动画不起作用
确保所有直接子元素都获得一个唯一的 key 属性,该属性对于每个渲染的组件保持不变。
例如,将 index 作为 key 是 不好的,因为如果项目重新排序,则 index 将不会与 item 匹配
<AnimatePresence> <Component v-for="(item,index) in items" :key="index" /> </AnimatePresence>
最好传递对该项目唯一的东西,例如 ID
<AnimatePresence> <Componen v-for="(item,index) in items" :key="item.id" /> </AnimatePresence>
还要确保 AnimatePresence 位于取消挂载元素的代码的外部。如果 AnimatePresence 自身被取消挂载,则它无法控制退出动画!
例如,这会 不起作用
<AnimatePresence v-if="isVisible"> <Component /> </AnimatePresence>
相反,条件应该位于 AnimatePresence 的根部
<AnimatePresence> <Component v-if="isVisible" /> </AnimatePresence>
布局动画在 mode="sync" 下不起作用
当混合布局和退出动画时,可能需要将组包裹在 LayoutGroup 中,以确保 AnimatePresence 外部的组件知道何时执行布局动画。
<LayoutGroup> <motion.ul layout> <AnimatePresence> <motion.li v-for="item in items" 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"> <motion.li v-for="item in items" layout :key="item.id" /> </AnimatePresence> </motion.ul>
