Vue 2 动效
过渡动效是主要针对元素素进入(显示)/离开(隐藏)和列表(重排)的情况设置动效,基于 CSS3 的 transition
和 animation
属性实现的。
Vue 中常见的触发动画的情况:
- 条件渲染
v-if
切换 - 条件显示
v-show
切换 - 动态组件属性
is
切换
元素进入/离开过渡
Vue 提供内置组件 <transition name="animationType"></transition>
作为容器,为包裹在其中的元素设置进入/离开时的动画。
当发生以上所说的触发动画的情况,Vue 会为容器内的元素插入相应的 class
属性,实现预设的动效,并在结束后移除 class
属性。
Vue 会在过渡的不同阶段,为元素==插入 6 种不同后缀的 class
属性==,可以使用这些 class
作为选择器,更精细地设置元素的在不同过渡阶段的样式:
v-enter
在元素被插入到页面之前生效,可以使用这个类名作为 CSS 选择器设置元素的初始样式v-enter-active
在整个进入过渡的阶段中应用,可以使用这个类名作为 CSS 选择器设置过渡效果,例如通过设置 CSS 属性transition
控制过渡缓和曲线v-enter-to
在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除v-leave
在离开过渡被触发时立刻生效v-leave-active
在整个离开过渡的阶段中应用,可以使用这个类名作为 CSS 选择器设置过渡效果,例如通过设置 CSS 属性transition
控制过渡缓和曲线和延迟时间等v-leave-to
定义离开过渡的结束状态(与此同时 v-leave 被删除),在过渡/动画完成之后移除
Tip
如果使用 animation
属性实现动效,而不是 transition
控制过渡,则不需要指定 v-enter
/v-leave
或 v-enter-to
/v-leave-to
的状态,只需要在 v-enter-active/v-leave-active
过渡中设定 CSS 属性 animation
即可,其中在关键帧中指定了 0%
和 100%
状态时的样式就是开始和结束的状态
Tip
以上 6 种不同后缀的 class
属性都使用了 v-
作为默认前缀,如果容器标签设置了属性 name
即 <transition name="animationType">
,则动态插入的 class
属性名称就会以 animationType-
为前缀,即 v-enter
会替换为 animationType-enter
,记得设置样式时使用相应的前缀,而不是默认前缀 v-
。
Tip
Vue 可以自动得出过渡效果的完成时机,以「拔除」添加到元素上的相关的 class
类名,但是如果(不推荐)同时使用了 CSS 的属性 trasition
和 animation
设置动画,可能会因为两种过渡时间不同,比如 animation
很快的被触发并完成了,而 transition
效果还没结束,而出现一些意想不到的动画 Bug,:IconCustom{name="mdi:youtube" iconClass="text-red-500"} 这时候可以为容器添加选项 type
并设置值为 animation
或 transition
来显式地声明你需要 Vue 监听的类型;也可以在容器元素上通过 prop 显式地指定持续时间(以毫秒计) <transition :duration="1000">
。
Warning
以上视频是基于 Vue 3 的,不过大部分内容都是兼容 Vue 2,具体区别可以查看相应的官方文档。
对于使用 v-if
/ v-else
实现的多元素之间进行切换时,需要注意相同标签名的元素要设置 key
属性作为唯一标识让 Vue
区分它们,否则只会替换相同标签内部的内容。另外在多元素过渡时,默认模式是两个元素的进入&离开是同时进行的,可能会导致页面布局乱掉,可以将模式改成 <transition mode="out-in"></transition>
让当前元素先进行过渡离开,完成之后新元素过渡进入
Tip
动效如果在初次加载页面时不生效,可以使用属性 appear
或 v-on:appear
钩子设置节点初始渲染的过渡
如果要用第三方的 CSS 动画库,如 Animate.css,需要在 DOM 元素上插入特定的类名来应用相应的 CSS 样式,可以在标签 <transition></transition>
上使用如下列出的 attribute,这样 Vue 会在过渡的相应阶段为容器内的元素相应地添加这些自定义过渡类名:
enter-class="custom-class-name"
在元素进入页面前添加的类名enter-active-class="custom-class-name"
enter-to-class="custom-class-name"
leave-class="custom-class-name"
leave-active-class="custom-class-name"
leave-to-class="custom-class-name"
Vue 除了会在过渡的不同阶段,为元素插入不同 class
类属性,还会同时触发相应事件,:IconCustom{name="mdi:youtube" iconClass="text-red-500"} 因此可以监听这些事件通过 JS 设置元素的 attribute 「手动」控制样式(或其他操作)实现动画:
v-on:before-enter="beforeEnter(el)"
可以传递执行动画的元素v-on:enter="enter(el, done)"
需要在回调函数中,在动画执行完成时调用done()
告知 Vue 动画结束。必须执行一次done()
,否则它们将被同步调用,过渡会立即完成。v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
元素离开页面触发的事件v-on:before-leave="beforeLeave"
v-on:leave="leave"
需要在回调函数中,在动画执行完成时调用done()
告知 Vue 动画结束。必须执行一次done()
,否则它们将被同步调用,过渡会立即完成。v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
Tip
推荐对于仅使用 JS 过渡的元素添加 v-bind:css="false"
,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
列表重排过渡
使用组件 <transition-group></transition-group>
作为容器,其中可以包裹多个节点(而 <transition>
只允许一个根节点;或者可以有多个元素,但是通过 v-if
或 v-show
控制元素的显示与隐藏,实际上每次也只能显示一个根节点),它默认渲染为一个 <span>
作为容器包裹列表,可以通过设置属性 tag="div"
更换为其他元素。内部的各个节点总是需要提供属性 key
作为唯一标识。
Vue 也是在过渡的不同阶段,为元素插入以上所述的 6 个不同后缀 class
,可以使用这些 class
作为选择器设置样式。
此外 Vue 还特别针对性地 新增了 v-move
类(即以 -move
为后缀,如果设置了 name
属性 <transition-group name="animationType"></transition-group>
,则列表重排时插入到列表项的 class
类属性的前缀就会改变,即为 animationType-move
),一般会通过这个 CSS 选择器设置 CSS 属性 transform
,然后 Vue 会使用 CSS 的属性 transform
将元素从之前的位置平滑过渡新的位置,实现一个称为 FLIP 的动画效果。
Tip
该动效对于 display: inline
元素无效,此时可以将元素,如 <span>
,设置为 display: inline-block
Play Videohttps://www.youtube.com/embed/WOJWsYe3JVY?start=5120&end=6135&modestbranding=1&rel=0
Tip
视频教程推荐使用一个 JS 库 Loadash 的 _.shuffle(collection)
方法对列表数据进行「洗牌」重排。
动态过渡
Vue 是数据驱动画面的,因此过渡动效的类型也可以进行控制,:IconCustom{name="mdi:youtube" iconClass="text-red-500"} 通过 <transition v-bind:name="transitionName">
将属性 name
绑定到变量,就可以改变动效的类型,例如轮播图点击左右箭头时,监听切换方向以修改 transitionName
,实现不同的切换方向应用不同的过渡效果。
Tip
想起之前遇到的一个 slide 库 reveal.js 感觉可以通过 Vue 的动态过渡来实现 😄
Good
找到一个叫 Slidev 的工具,这个幻灯片制作工具旨在为开发者提供灵活性和交互性支持,功能更丰富,不过仍处于 Beta 版本。