~ 单元素 / 组件的过渡
过渡的-CSS-类名
会有 4 个(CSS)类名在 enter/leave 的过渡中切换:

v-enter: 定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。v-enter-active: 定义进入过渡的结束状态。在元素被插入时生效,在 过渡/动画 完成之后移除。v-leave: 定义离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。v-leave-active: 定义离开过渡的结束状态。在离开过渡被触发时生效,在 过渡/动画 完成之后移除。
对于这些在 enter/leave过渡中切换的类名,v-是这些类名的前缀。
使用 <name="my-transition>"可以重置前缀,比如 v-enter替换为 my-transition-enter。
[ CSS 过渡 ] 常用的过渡都是使用 CSS 过渡。
<div id="example-1"> <button @click="show = !show"> Toggle render </button> <transition name="slide-fade"> <p v-if="show">hello</p> </transition> </div>new Vue({ el: '#example-1', data: { show: true } })/* 可以设置不同的进入和离开动画 */ /* 设置持续时间和动画函数 */ .slide-fade-enter-active { transition: all .3s ease; } .slide-fade-leave-active { transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0); } .slide-fade-enter, .slide-fade-leave-active { padding-left: 10px; opacity: 0; }
[ CSS 动画 ] CSS 动画用法同 CSS 过渡,区别是在动画中
v-enter类名在节点插入 DOM 后不会立即删除,而是在animationend事件触发时删除。 // 以下代码省略了兼容性前缀<div id="example-2"> <button @click="show = !show">Toggle show</button> <transition name="bounce"> <p v-if="show">Look at me!</p> </transition> </div>new Vue({ el: '#example-2', data: { show: true } }).bounce-enter-active { animation: bounce-in .5s; } .bounce-leave-active { animation: bounce-out .5s; } @keyframes bounce-in { 0% { transform: scale(0); } 50% { transform: scale(1.5); } 100% { transform: scale(1); } } @keyframes bounce-out { 0% { transform: scale(1); } 50% { transform: scale(1.5); } 100% { transform: scale(0); } }
自定义过渡类名(常用于动画库)
我们可以通过以下特性来自定义过渡类名:
enter-classenter-active-classleave-classleave-active-class
他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css结合使用十分有用。
<link href="https://unpkg.com/animate.css@3.5.1/animate.min.css" rel="stylesheet" type="text/css">
<div id="example-3">
<button @click="show = !show">
Toggle render
</button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">hello</p>
</transition>
</div>
new Vue({
el: '#example-3',
data: {
show: true
}
})
[ 同时使用 Transitions 和 Animations ]
Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是
transitionend或animationend,这取决于给元素应用的 CSS 规则。如果你使用其中任何一种,Vue 能自动识别类型并设置监听。但是,在一些场景中,你需要给同一个元素同时设置两种过渡动效,比如animation很快的被触发并完成了,而transition效果还没结束。在这种情况中,你就需要使用
type特性并设置animation或transition来明确声明你需要 Vue 监听的类型。
JavaScript 钩子
可以在属性中声明 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>
// ...
methods: {
// --------
// 进入中
// --------
beforeEnter: function (el) {
// ...
},
// 此回调函数是可选项的设置
// 与 CSS 结合时使用
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// 离开时
// --------
beforeLeave: function (el) {
// ...
},
// 此回调函数是可选项的设置
// 与 CSS 结合时使用
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}
这些钩子函数可以结合 CSS
transitions/animations使用,也可以单独使用。当只用 JS 过渡的时候, 在进入/离开时,回调函数 done 是必须的 。否则,它们会被同步调用,过渡会立即完成。 推荐对于仅使用 JS 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
// 代码示例:一个使用 Velocity.js 的简单例子
<!--
Velocity works very much like jQuery.animate and is
a great option for JavaScript animations
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="example-4">
<button @click="show = !show">
Toggle
</button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:css="false"
>
<p v-if="show">
Demo
</p>
</transition>
</div>
new Vue({
el: '#example-4',
data: {
show: false
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0
},
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 })
}
}
})