vue2动画
在Vue.js 2中,动画和过渡是通过<transition>
和<transition-group>
组件来实现的
<transition>
组件
<transition>
组件包裹单个元素或组件,并在它们渲染、更新或从DOM中移除时触发过渡效果。这个组件不会渲染为任何额外的DOM元素,它只应用于内部的单个元素或组件。
作用:
- 在元素或组件的进入和离开过渡时添加动画。
- 自动应用过渡的类名,以便开发者可以定义CSS过渡或动画。
- 提供JavaScript钩子函数,允许开发者在过渡的不同阶段执行自定义逻辑。
- 支持多种过渡模式,如同时进行的进入和离开过渡,或者等待一个元素过渡完成后才开始另一个元素的过渡。
示例:
<transition name="fade">
<div v-if="show">This element will fade in and out.</div>
</transition>
在上面的例子中,当show
的值发生变化时,包裹的<div>
元素会根据show
的布尔值进行过渡。过渡的名称为fade
,Vue会自动将相关的类名(如fade-enter-active
、fade-leave-active
等)添加到元素上,以触发定义在CSS中的过渡效果。
<transition-group>
组件
<transition-group>
组件用于包裹一组动态的元素,通常是v-for
渲染的列表,并且在列表元素进入、离开或顺序改变时添加动画效果。与<transition>
不同的是,<transition-group>
会渲染为一个真实的DOM元素,默认为<span>
,但可以通过tag
属性来指定为其他元素。
作用:
- 管理列表中多个元素的过渡效果。
- 在列表的元素位置改变时提供动画,例如排序操作。
- 保持列表元素的DOM状态和内部组件状态,在列表变动时不会重新渲染整个列表。
- 每个列表元素都需要一个唯一的
key
属性,这样Vue才能够追踪每个元素的状态。
示例:
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</transition-group>
在上述例子中,<transition-group>
包裹了一个v-for
渲染的<li>
元素列表。每个<li>
元素都有一个唯一的key
属性,这样Vue就可以正确地应用过渡效果,即使列表的顺序发生了变化。过渡的名称为list
,Vue将自动添加相关的过渡类名到每个<li>
元素上。
使用<transition>
和<transition-group>
组件可以大大增强Vue应用的用户体验,通过平滑的过渡效果引导用户的注意力,并且给予用户操作的直观反馈。
描述Vue.js是如何处理元素的进入和离开过渡的。
Vue.js 通过 <transition>
和 <transition-group>
组件提供了一种声明式的方法来处理元素和组件的进入(enter)和离开(leave)过渡。以下是Vue.js如何处理这些过渡的步骤:
进入过渡 (Enter Transition)
- 检测条件: Vue.js 首先检测是否有条件触发了元素的进入,例如绑定到
v-if
或v-show
的数据变为真值,或者一个列表项被v-for
渲染出来。 - 初始类名: 在元素被插入到DOM之前,Vue.js 会添加
*-enter
和*-enter-active
类名。这里的*
是<transition>
组件的name
属性值,如果没有设置name
,默认为v
。 - 插入DOM: 元素被插入到DOM中,此时
*-enter
类名定义的样式被应用,通常是元素的初始状态。 - 下一个帧: Vue会在下一个帧(即浏览器的下一个重绘周期)移除
*-enter
类名,并添加*-enter-to
类名。这通常会触发一个过渡或动画,因为元素的状态从*-enter
变成了*-enter-to
。 - 过渡/动画结束: 过渡或动画完成后,
*-enter-active
和*-enter-to
类名被移除。如果定义了JavaScript钩子,after-enter
钩子函数将被调用。
离开过渡 (Leave Transition)
- 检测条件: Vue.js 检测到条件触发了元素的离开,例如绑定到
v-if
或v-show
的数据变为假值,或者一个列表项由于数据变化不再被v-for
渲染。 - 初始类名: 在元素离开之前,Vue.js 会添加
*-leave
和*-leave-active
类名。 - 下一个帧: 在下一个帧,Vue移除
*-leave
类名并添加*-leave-to
类名,触发过渡或动画。 - 过渡/动画结束: 一旦过渡或动画完成,元素会从DOM中移除,同时
*-leave-active
和*-leave-to
类名也被移除。如果定义了JavaScript钩子,after-leave
钩子函数将被调用。
在整个过渡过程中,Vue.js 会自动处理样式的添加和删除,开发者只需定义相应的CSS过渡或动画规则,或者使用JavaScript钩子函数来自定义过渡行为。这种自动化的处理机制使得在Vue应用中实现复杂的交互动效变得简单而高效。
过渡的钩子函数
Vue.js 提供了一系列的 JavaScript 钩子函数,允许你在元素的过渡过程中的不同阶段执行自定义 JavaScript 逻辑。以下是这些过渡钩子函数的列表和说明:
before-enter
:- 在过渡开始之前调用,此时元素尚未插入DOM。
- 用于在过渡开始之前应用初始样式或执行设置。
enter
:- 在过渡开始后立即调用,此时元素已插入DOM。
- 用于激活过渡的动效,通常结合
done
回调来使用,以确定何时过渡结束。
after-enter
:- 在过渡结束后调用。
- 用于清理过渡后的状态,或执行过渡完成后的逻辑。
enter-cancelled
:- 在过渡被取消时调用,例如在过渡进行中移除了过渡元素。
- 用于清理被取消过渡的状态。
before-leave
:- 在离开过渡开始之前调用,此时元素仍在DOM中。
- 用于在过渡开始之前执行设置。
leave
:- 在离开过渡开始后立即调用。
- 用于激活离开的动效,通常结合
done
回调来使用,以确定何时过渡结束。
after-leave
:- 在离开过渡结束后调用。
- 用于清理离开过渡后的状态,或执行过渡完成后的逻辑。
leave-cancelled
:- 在离开过渡被取消时调用,例如在离开过渡进行中又重新插入了元素。
- 用于清理被取消离开过渡的状态。
这些钩子函数可以直接在 <transition>
组件上使用,并且可以接收元素作为参数。如果使用 enter
或 leave
钩子,还可以接收 done
回调作为第二个参数,用于在动画结束时调用。
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<div v-if="show">This element will transition in and out</div>
</transition>
<script>
export default {
methods: {
beforeEnter(el) {
// 元素过渡前的准备工作
},
enter(el, done) {
// 执行过渡动效
// 当动效完成后调用 done()
done();
},
afterEnter(el) {
// 过渡完成后的清理工作
},
enterCancelled(el) {
// 过渡取消时的清理工作
},
beforeLeave(el) {
// 离开过渡前的准备工作
},
leave(el, done) {
// 执行离开动效
// 当动效完成后调用 done()
done();
},
afterLeave(el) {
// 离开过渡完成后的清理工作
},
leaveCancelled(el) {
// 离开过渡取消时的清理工作
}
}
}
</script>
在实际应用中,你可以根据需要选择性地使用这些钩子函数来实现复杂的过渡效果,例如与第三方动画库协同工作,或者在过渡过程中同步其他动作。
解释Vue.js中的过渡类名,如enter
、enter-active
、enter-to
、leave
、leave-active
和leave-to
在Vue.js中,当使用 <transition>
组件时,Vue会在元素的进入和离开过渡时自动应用一系列的类名。这些类名是按照特定的顺序和时间添加和删除的,以实现CSS过渡和动画效果。以下是这些类名的说明及它们在过渡过程中的作用:
enter
: 应用在进入过渡的开始阶段,定义进入开始时的初始状态。在下一个帧移除。enter-active
: 在整个进入过渡过程中应用,并定义过渡的持续时间、属性和曲线。这个类可以与CSS的transition
属性或animation
属性配合使用。enter-to
: 应用在进入过渡的结束状态,定义进入结束时的最终状态。在过渡/动画完成后移除。在2.1.8版本及以上,这个类取代了enter
类在过渡开始后的作用。leave
: 应用在离开过渡的开始阶段,定义离开开始时的初始状态。在下一个帧移除。leave-active
: 在整个离开过渡过程中应用,并定义过渡的持续时间、属性和曲线。这个类可以与CSS的transition
属性或animation
属性配合使用。leave-to
: 应用在离开过渡的结束状态,定义离开结束时的最终状态。在过渡/动画完成后移除。在2.1.8版本及以上,这个类取代了leave
类在过渡开始后的作用。
<transition name="fade">
<div v-if="show">Fade Transition</div>
</transition>
<style>
/* 进入和离开的激活状态 */
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
/* 进入的起始状态和离开的结束状态 */
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
在上面的例子中,.fade-enter-active
和 .fade-leave-active
类定义了过渡的持续时间和属性(在这里是半透明效果)。.fade-enter
和 .fade-leave-to
类定义了元素进入和离开时的起始和结束状态。
当你希望自定义这些类名时,可以通过 <transition>
组件的 name
属性来设置前缀,Vue将使用这个前缀来构建上述的过渡类名。例如,如果你设置 name="fade"
,Vue将应用 .fade-enter
、.fade-enter-active
等类名。如果没有设置 name
属性,默认使用 v
前缀,如 v-enter
、v-enter-active
等。
区分CSS过渡(transition
)和CSS动画(animation
)在Vue.js中的使用方式。
在Vue.js中,你可以使用CSS过渡(transition
)和CSS动画(animation
)来为元素添加进入和离开的动效。它们都可以通过Vue的 <transition>
组件来实现,但它们在定义和触发动画的方式上有所不同。
CSS过渡 (transition
): CSS过渡用于在元素的两个状态之间插入一个过渡效果。通常,它是在一个属性值改变时发生,比如在悬停或者元素被插入/移除DOM时。在Vue中,当使用 <transition>
包裹元素时,Vue会在适当的时机添加/删除特定的类名来触发过渡。
<transition name="fade">
<div v-if="show">This will fade in and out</div>
</transition>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
在上面的例子中,.fade-enter-active
和 .fade-leave-active
是应用过渡效果的类,它们定义了过渡的持续时间和效果(在这里是半透明)。.fade-enter
和 .fade-leave-to
定义了元素进入和离开时的起始和结束状态。
CSS动画 (animation
): CSS动画允许你创建复杂的动画序列,它们不依赖于元素状态的改变。动画可以在一段时间内多次改变多个CSS属性值。在Vue中,动画也是通过 <transition>
组件的类名触发的。
<transition name="slide">
<div v-if="show">This will slide in and out</div>
</transition>
<style>
.slide-enter-active {
animation: slide-in .5s;
}
.slide-leave-active {
animation: slide-out .5s;
}
@keyframes slide-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
@keyframes slide-out {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
</style>
在这个例子中,.slide-enter-active
和 .slide-leave-active
类定义了动画的名称和持续时间。@keyframes
规则定义了动画的中间步骤。
主要区别:
- 触发时机: CSS过渡是在某个CSS属性发生变化时触发的,而CSS动画是在页面加载、元素插入或者通过添加类名时就可以立即开始的。
- 定义方式: CSS过渡通常是简单的两种状态之间的变化,而CSS动画通过
@keyframes
可以定义更复杂的多状态动画。 - 控制: CSS动画提供了更多控制动画序列的能力,如迭代次数、方向、延迟等。
在Vue.js中,你可以根据需要选择使用CSS过渡还是CSS动画来达到所需的动效效果。过渡更适合简单的状态变化,而动画则适合更复杂的连续动效。
说明如何将第三方动画库(如Animate.css)与Vue的过渡系统集成。
将第三方动画库(如 Animate.css)与 Vue 的过渡系统集成是一个相对简单的过程。以下是如何将 Animate.css 与 Vue 集成的步骤:
- 引入第三方动画库: 首先,你需要将 Animate.css 引入到你的项目中。这可以通过在项目的 HTML 文件中添加
<link>
标签来实现,或者在你的 JavaScript 文件中使用import
语句(如果你的项目支持模块化)。
<!-- 在 HTML 文件中添加 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
或者
// 在 JavaScript 文件中添加
import 'animate.css/animate.min.css';
- 使用
<transition>
组件: 在你的 Vue 组件中,使用<transition>
组件包裹你想要应用动画的元素。设置name
属性或者直接使用enter-active-class
和leave-active-class
属性来指定 Animate.css 的动画类。
<transition
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOut"
>
<div v-if="show">This element will bounce in and out.</div>
</transition>
在上面的例子中,我们使用了 Animate.css 提供的 animate__animated
类来触发动画,并指定了具体的动画效果(animate__bounceIn
和 animate__bounceOut
)。
-
控制动画的显示和隐藏: 使用 Vue 的响应式系统(如
v-if
、v-show
或v-for
)来控制元素的显示和隐藏。当这些条件发生变化时,Vue 会自动应用和移除 Animate.css 的动画类,从而触发动画效果。 -
调整动画持续时间: 如果需要,你可以通过 Animate.css 的类或自定义 CSS 来调整动画的持续时间、延迟或其他属性。
<style>
.custom-duration {
--animate-duration: 2s;
}
</style>
<transition
enter-active-class="animate__animated custom-duration animate__bounceIn"
leave-active-class="animate__animated custom-duration animate__bounceOut"
>
<div v-if="show">This element will bounce in and out with a custom duration.</div>
</transition>
- 处理 JavaScript 钩子: 如果需要更细粒度的控制,你可以使用
<transition>
组件的 JavaScript 钩子(如before-enter
、enter
、after-enter
等)来协同第三方动画库。
这样,你就可以在 Vue 应用中利用 Animate.css 提供的丰富动画效果,同时享受 Vue 过渡系统的便利性和灵活性。
解释<transition-group>
的特殊用途和它如何处理列表的过渡。
<transition-group>
组件在 Vue.js 中用于处理一组元素的过渡效果,尤其是当这些元素是动态渲染的,如通过 v-for
循环渲染的列表。与 <transition>
组件不同的是,<transition-group>
专门设计来处理多个元素同时进行的过渡,并且它能够处理元素位置的改变。
特殊用途
- 列表过渡:
<transition-group>
组件常用于实现列表项的进入、离开和位置变化的过渡效果。这对于动态列表非常有用,如待办事项列表、购物车或任何由用户操作导致项顺序变动的场景。 - 位置变化的过渡: 当列表中元素的顺序变化时,
<transition-group>
会使用一个叫做“FLIP”(First, Last, Invert, Play)的动画技术来平滑地过渡元素的位置。这意味着元素即使在页面布局中重新排序,也能够以动画的形式从一个位置平滑地移动到另一个位置。
处理列表过渡
<transition-group>
组件如何处理列表的过渡:
- 渲染为实际的DOM元素:
<transition-group>
默认渲染为一个<span>
元素,但你可以通过tag
属性指定任何其他有效的HTML元素作为其渲染标签。 - 要求唯一的key: 列表中的每个元素都必须有一个唯一的
key
属性,这样 Vue 才能够正确追踪每个元素的状态和位置。 - 自动过渡类名应用: 类似于
<transition>
,<transition-group>
会在子元素进入和离开时自动应用过渡类名。这些类名可以用来定义CSS过渡或动画。 - 使用CSS过渡或JavaScript钩子: 你可以定义CSS过渡或使用JavaScript钩子来创建复杂的动画效果,同样的,这些动画可以应用于进入、离开和列表顺序变化。
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id" class="list-item">
{{ item.text }}
</li>
</transition-group>
<style>
.list-item {
transition: all 1s;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(30px);
}
</style>
在上面的示例中,我们创建了一个 <transition-group>
,用来渲染一个 <ul>
列表,并给每个 <li>
元素添加了进入和离开的过渡效果。每个元素在进入时都会从下方移动并淡入,离开时则淡出上移。
通过 <transition-group>
,开发者可以轻松为列表和网格布局中的多个元素添加动画,无论是它们进入/离开的过渡,还是在列表中位置变化的过渡,Vue.js 都能够提供一种优雅且性能高效的解决方案。
为何<transition-group>
渲染为真实的DOM元素
<transition-group>
组件在 Vue.js 中的设计是为了管理一组动态元素的过渡效果,特别是当这些元素需要在列表中进行排序或位置变动时。与 <transition>
组件不同,<transition-group>
需要渲染为真实的 DOM 元素,这是由于两个主要原因:
- 维持内部元素的相对位置: 当列表中的元素进行排序或位置变动时,
<transition-group>
组件需要维护它们的相对位置,以便可以应用 FLIP(First, Last, Invert, Play)动画技术。这种技术涉及到计算元素的初始位置和最终位置,并应用一个平滑的转换动画。为了实现这种位置的跟踪和转换,每个元素必须位于一个共同的父容器内。 - 提供一个稳定的上下文:
<transition-group>
组件通过渲染为一个真实的 DOM 元素,为其子元素提供一个稳定的上下文。这有助于 Vue.js 在执行过渡动画时,更好地管理元素的插入、更新和移除操作。如果<transition-group>
不渲染为一个真实的 DOM 元素,那么在执行列表元素的过渡动画时,可能会出现元素的定位问题,从而导致动画效果不准确。
讨论在实现动画时需要考虑的性能问题
在实现动画时,考虑性能问题是非常重要的,因为动画可能会对网站或应用的性能产生显著影响,尤其是在低性能设备或大量元素动画的情况下。以下是在实现动画时需要考虑的一些性能问题:
- 避免重排和重绘:
- 重排(Reflow)和重绘(Repaint)是浏览器渲染过程中最耗性能的部分。尽量减少动画中触发重排和重绘的属性。例如,使用
transform
和opacity
进行动画,因为它们可以由合成器处理,而不需要更新布局或绘制。
- 重排(Reflow)和重绘(Repaint)是浏览器渲染过程中最耗性能的部分。尽量减少动画中触发重排和重绘的属性。例如,使用
- 硬件加速:
- 利用硬件加速可以提高动画的性能。在现代浏览器中,使用 CSS 的
transform
和opacity
属性可以触发硬件加速,让动画更加平滑。
- 利用硬件加速可以提高动画的性能。在现代浏览器中,使用 CSS 的
- 减少动画的复杂度:
- 简化动画效果,减少动画中使用的元素数量和动画步骤,这样可以减少浏览器的计算量。
- 合理安排动画时间:
- 不要让动画运行的时间太长,这会让用户感到不耐烦,并且占用浏览器资源。同时,避免太多动画同时进行,这可能会导致帧率下降。
- 使用
requestAnimationFrame
:- 对于复杂的 JavaScript 动画,使用
requestAnimationFrame
而不是setTimeout
或setInterval
。requestAnimationFrame
会在浏览器重绘之前执行动画更新,这样可以保证动画的流畅性。
- 对于复杂的 JavaScript 动画,使用
- 优化动画队列:
- 如果有多个动画序列,考虑是否可以合并或串行执行,以减少同时进行的动画数量。
- 测试不同设备和浏览器:
- 在不同的设备和浏览器上测试动画效果,因为它们的性能和渲染行为可能不同。
- 使用
will-change
属性:- 对即将发生动画的元素使用 CSS 的
will-change
属性,可以通知浏览器预先优化,但要谨慎使用,因为过度使用可能导致性能问题。
- 对即将发生动画的元素使用 CSS 的
- 限制动画的范围:
- 对于大型的动画元素,限制其动画影响的范围。例如,可以使用
overflow: hidden
属性来剪切不需要显示的部分。
- 对于大型的动画元素,限制其动画影响的范围。例如,可以使用
- 分析性能:
- 使用浏览器的开发者工具来分析动画的性能。例如,Chrome 的 Performance 面板可以帮助你识别性能瓶颈。
通过考虑这些性能问题并采取相应的优化措施,你可以确保动画不仅能提供出色的用户体验,而且不会对应用的整体性能造成不利影响。
解释<transition>
组件的mode
属性,包括in-out
和out-in
模式
<transition>
组件的 mode
属性用于控制进入和离开过渡的时序。默认情况下,进入和离开过渡同时进行。然而,在某些情况下,你可能希望一个过渡完成后再开始另一个过渡。这时,mode
属性就变得非常有用。它主要有两个值:in-out
和 out-in
。
in-out
模式
在 in-out
模式下,新元素先进行过渡,完成后旧元素过渡出去。这意味着新元素进入的过渡会立即开始,不管旧元素的离开过渡是否已经开始或完成。一旦新元素的进入过渡完成,旧元素的离开过渡才会开始。
这种模式适合场景,如当用户需要关注新内容的呈现时,而旧内容的消失可以稍后进行,不需要立即引起注意。
<transition mode="in-out">
<div v-if="show" key="1">New Element</div>
<div v-else key="2">Old Element</div>
</transition>
在上面的例子中,如果 show
的值发生变化,那么 “New Element” 将立即开始进入过渡。只有在 “New Element” 的进入过渡完成之后,”Old Element” 的离开过渡才会开始。
out-in
模式
在 out-in
模式下,旧元素先进行过渡,完成后新元素过渡进入。这意味着旧元素的离开过渡会立即开始,新元素不会开始过渡,直到旧元素的过渡完成。
这种模式适合场景,如当需要用户注意离开的内容时,确保用户不会错过重要的离开动作或状态变化,然后再将注意力转移到新元素上。
<transition mode="out-in">
<div v-if="show" key="1">New Element</div>
<div v-else key="2">Old Element</div>
</transition>
在上面的例子中,如果 show
的值发生变化,那么 “Old Element” 将立即开始离开过渡。只有在 “Old Element” 的离开过渡完成之后,”New Element” 的进入过渡才会开始。
使用 mode
属性可以让你更精确地控制过渡的顺序和时序,从而创建更丰富和更符合用户预期的动画效果。这对于防止过渡之间的冲突,以及确保用户能够平滑地从一个应用状态过渡到另一个状态非常有帮助。
原文链接:https://juejin.cn/post/7357916775960821772 作者:biye君