元素/组件过渡
Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/ 离开过渡。
条件渲染 (使用 v-if)。
条件展示 (使用 v-show)。
动态组件。
组件根节点。
语法格式如
<transition name = "nameoftransition"><div></div></transition>
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><!--引入 vue--><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head><body><div id="demo"><button v-on:click="show = !show">点我</button><transition name="fade"><p v-if="show">动画实例</p></transition></div><script>new Vue({el: '#demo',data: {show: true}})</script></body></html>
实例中通过点击 “点我” 按钮将变量 show 的值从 true 变为 false。如果为 true 显示 子元素 p 标签的内容。
实例中通过点击 “点我” 按钮将变量 show 的值从 true 变为 false。如果为 true 显示 子元素 p 标签的内容。
<transition name="fade"><p v-if="show">动画实例</p></transition>
当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删 除 CSS 类名。
如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插 入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概 念不同)。
过渡其实就是一个淡入淡出的效果。Vue在元素显示与隐藏的过渡中,提供了 6 个 class 来切换

对于这些在过渡中切换的类名来说,如果你使用一个没有名字的
CSS 过渡
常用的 Vue 过渡效果都是使用 CSS 过渡 transition。我们首先看一个简单的切换显示按 钮,
<div id="app"><button @click="show=!show">点我</button><div v-if="show">Hello world</div></div><script>new Vue({el: '#app',data: {show: true}})</script>
我们现在希望 Hello world 能有一个渐隐渐现的效果,那么就需要在 div 外层包裹一个 transition 标签
<div id="app"><button @click="show=!show">点我</button><transition name="fade"><div v-if="show">Hello world</div></transition></div>
当然只是这样也是无法形成过渡效果的。仍需在 transition 标签中添加 class 样式,只不过 class 样式不需要我们手动添加,Vue 在运行中会自动的构建一个动画的流程

当动画执行的一瞬间,会自动在 div 上增加两个 class 名字,分别是 fade-enter 和 fade-enter-active,因为 transiton 标签 name 是 fade。
当动画运行到第二帧时,Vue 又会把 fade-enter 删除,然后添加一个 fade-enter-to,再当动画执行到结束的一瞬间,又把 fade-enter-active 和 fade-enter-to 删除掉
<head><style>.fade-enter{opacity: 0;}.fade-enter-active{transition: opacity 3s;}</style></head><body><div id="app"><button @click="show=!show">点我</button><transition name="fade"><div v-if="show">Hello world</div></transition></div><script>new Vue({el: '#app',data: {show: true}})</script></body>
在上 图 Vue动画过渡图中,我们发现fade-enter-active是全程存在的,它的作用是,如果监听到了元素opacity发生了变化,那么就让这个变化在3s内完成。
再来看Vue元素从显示到隐藏的动画效果,代码如下:
<style>.v-enter{opacity: 0;}.v-enter-active{transition: opacity 3s;}.v-leave-to{opacity: 0;}.v-leave-active{transition: opacity 3s;}</style>
CSS 动画
CSS动画animation用法同CSS过渡transition,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除,。
在元素 enter 和 leave 时都增加缩放 scale 效果
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><!--引入vue--><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>.bounce-enter-active{animation:bounce-in .5s;}.bounce-leave-active{animation:bounce-in .5s reverse;}@keyframes bounce-in{0%{transform:scale(0);}50%{transform:scale(1.5);}100%{transform:scale(1);}}</style></head><body><div id="app"><button v-on:click="show = !show">点我</button><transition name="bounce"><p v-if="show">Hello World</p></transition></div><script>new Vue({el: '#app',data: {show: true}})</script></body></html>
Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是 transitionend 或 animationend ,这取决于给元素应用的 CSS 规则。如果使用其中任何一种,Vue 能自动识 别类型并设置监听。
在一些场景中,需要给同一个元素同时设置两种过渡动效。
css 过渡和动画同时使用
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><!--引入 vue--><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>.fade-enter,.fade-leave-to{opacity:0;}.fade-enter-active,.fade-leave-active{transition:opacity 1s;animation:bounce-in 5s;}@keyframes bounce-in{0%{transform:scale(0);}50%{transform:scale(1.5);}100%{transform:scale(1);}}</style></head><body><div id="app"><button v-on:click="show = !show">点我</button><transition name="fade" type="transition"><p v-if="show">Hello World</p></transition></div><script>new Vue({el: '#app',data: {show: true,},})</script></body></html>
使用过渡类实现动画
自定义过渡的类名
通过以下特性来自定义过渡类名
enter-class
enter-active-class
leave-class
leave-active-class
他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库, 如 Animate.css 结合使用十分有用。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><!--引入 vue--><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>.fade-in-active, .fade-out-active{transition: all 1.5s ease}.fade-in-enter, .fade-out-active{opacity: 0}</style></head><body><div id="app"><button @click="show = !show">点我</button><transition name="fade"enter-class="fade-in-enter"enter-active-class="fade-in-active"leave-class="fade-out-enter"leave-active-class="fade-out-active"><p v-show="show">hello</p></transition></div><script>new Vue({el: '#app',data: {show: true}})</script></body></html>
上面代码中,原来默认的 fade-enter 类对应 fade-in-enter,fade-enter-active 类对应 fade-in-active,依次类推
CSS过渡钩子函数
除了用CSS过渡的动画来实现Vue的组件过渡,还可以用JavaScript的钩子函数来实现,在钩子函数中直接操作DOM。可以在属性中声明 JavaScript 钩子,代码如下:
<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" > <!-- ... --> </transition>
Js 代码
// ...methods: {// --------// 进入中// --------beforeEnter: function (el) {// ...},// 当与 CSS 结合使用时// 回调函数 done 是可选的enter: function (el, done) {// ...done()},afterEnter: function (el) {// ...},enterCancelled: function (el) {// ...},// --------// 离开时// --------beforeLeave: function (el) {// ...},// 当与 CSS 结合使用时// 回调函数 done 是可选的leave: function (el, done) {// ...done()},afterLeave: function (el) {// ...},// leaveCancelled 只用于 v-show 中leaveCancelled: function (el) {// ...}}
这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。
引入Velocity.js 来配合使用 JavaScript 过渡
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><!--引入 vue--><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!--Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒 的选择--><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.j s"></script></head><body> <div id="app"><button @click="show = !show">点我</button><transitionv-on:before-enter="beforeEnter"v-on:enter="enter"v-on:leave="leave"v-bind:css="false"><p v-if="show">Hello</p></transition></div><script>new Vue({el: '#app',data: {show: false},methods: {beforeEnter: function (el) {el.style.opacity = 0el.style.transformOrigin = 'left'},enter: function (el, done) {Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration:300 })Velocity(el, { fontSize: '1em' }, { complete: done })},leave: function (el, done) {Velocity(el, { translateX: '15px', rotateZ: '50deg' },{ duration: 600 })Velocity(el, { rotateZ: '100deg' }, { loop: 2 })Velocity(el, {rotateZ: '45deg',translateY: '30px',translateX: '30px',opacity: 0}, { complete: done })}}})</script></body> </html>
