- Vue provides a variety of ways to apply transition effects when items are inserted, updated, or removed from the DOM.
- On this page, we’ll only cover **entering, leaving, **and list transitions, but you can see the next section for managing state transitions.
DOM操作时的过渡效果,让页面更丝滑。
先来个demo开开胃,完整代码
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
style>
<div id="demo">
<button v-on:click="show = !show">
Toggle
button>
<transition name="fade">
<p v-if="show">hellop>
transition>
div>
<script>
new Vue({
el: '#demo',
data: {
show: true
}
})
script>
There are six classes applied for enter/leave transitions.
enter/leave过渡中,会有6个class切换
v-enter
v-enter-active
v-enter-to
(2.1.8+)v-leave
v-leave-active
v-leave-to
(2.1.8+)即给上面例子中的 .fade-enter-active, .fade-leave-active 这些类名应用的CSS样式
写法差不多,就是把transition换成animation 完整代码
<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>
<div id="example-2">
<button @click="show = !show">Toggle showbutton>
<transition name="bounce">
<p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.p>
transition>
div>
<script>
new Vue({
el: '#example-2',
data: {
show: true
}
})
script>
我们可以通过以下 attribute 来自定义过渡类名:
enter-class
enter-active-class
enter-to-class
(2.1.8+)leave-class
leave-active-class
leave-to-class
(2.1.8+)如下与 Animate.css的结合使用:完整代码
<link href="https://cdn.jsdelivr.net/npm/[email protected]" 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">hellop>
transition>
div>
<script>
new Vue({
el: '#example-3',
data: {
show: true
}
})
script>
要同时使用过渡和动画,要用type
属性指明类型:animation
or transition
<transition :duration="1000">...transition>
<transition :duration="{ enter: 500, leave: 800 }">...transition>
用js代码操作动画
如下使用了Velocity.js动画库,完整代码
<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>
<script>
new Vue({
el: '#example-4',
data: {
show: false
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0
el.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>
If you also want to apply a transition on the initial render of a node, you can add the
appear
attribute:
一个DOM节点初始化渲染到页面时可以引用过渡效果
<transition appear>
transition>
// 【还自定义class】
<transition
appear
appear-class="custom-appear-class"
appear-to-class="custom-appear-to-class" (2.1.8+)
appear-active-class="custom-appear-active-class"
>
transition>
// 【也可以自定义js钩子】
<transition
appear
v-on:before-appear="customBeforeAppearHook"
v-on:appear="customAppearHook"
v-on:after-appear="customAfterAppearHook"
v-on:appear-cancelled="customAppearCancelledHook"
>
transition>
一个常见的场景就是:渲染列表元素时,如果列表是空的,则渲染一个代表空列表的元素
<transition>
<table v-if="items.length > 0">
table>
<p v-else>Sorry, no items found.p>
transition>
需要注意:如果两个tag名一样的元素之间做过渡时,要加key
demo如下:
<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>
<div id="app">
<transition name="bounce">
<button v-bind:key="docState">
{{ buttonMessage }}
button>
transition>
<button @click="savebutton">切换按钮button>
div>
<script>
new Vue({
el: '#app',
data: {
docState: 'saved'
},
computed:{
buttonMessage: function () {
switch (this.docState) {
case 'saved': return 'Edit'
case 'edited': return 'Save'
}
}
},
methods: {
savebutton:function () {
if(this.docState == 'edited'){
this.docState = 'saved'
}else {
this.docState = 'edited'
}
}
}
})
script>
完整代码
可以设置两种过渡模式:
in-out
: New element transitions in first, then when complete, the current element transitions out.
out-in
: Current element transitions out first, then when complete, the new element transitions in.
我们来对比下设置了out-in
模式和不设置的区别吧:给上面例子上的transition加上mode属性为out-in
<transition name="bounce" mode="out-in">
<button v-bind:key="docState">
{{ buttonMessage }}
button>
transition>
组件之间的过渡更加简单,写法和元素一样,不需要加key
:
<style>
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
style>
<div id="app">
<input type="radio" value="v-a" id="a" name="view" @change="view='v-a'">
<label for="a">Alabel>
<input type="radio" value="v-b" id="b" name="view" @change="view='v-b'">
<label for="b">Blabel>
<transition name="component-fade" mode="out-in">
<component v-bind:is="view">component>
transition>
div>
<script>
new Vue({
el: '#app',
data: {
view: 'v-a'
},
components: {
'v-a': {
template: 'Component A'
},
'v-b': {
template: 'Component B'
}
}
})
script>
完整代码
列表的Entering/Leaving过渡、Move Transitions移动过渡,用
有几个注意点:
tag
标签指定,如下例子中指定为 tag='p'
key
<style>
.list-complete-item {
transition: all 1s;
display: inline-block;
margin-right: 10px;
}
.list-complete-enter, .list-complete-leave-to
/* .list-complete-leave-active below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
.list-complete-leave-active {
position: absolute;
}
style>
<div id="list-demo">
<button v-on:click="shuffle">Shufflebutton>
<button v-on:click="add">Addbutton>
<button v-on:click="remove">Removebutton>
<transition-group name="list-complete" tag="p">
<span v-for="item in items" v-bind:key="item" class="list-complete-item">
{{ item }}
span>
transition-group>
div>
<script>
new Vue({
el: '#list-demo',
data: {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
shuffle: function () {
this.items = _.shuffle(this.items)
}
}
})
script>
完整代码
上面演示了列表内元素进入/离开时的过渡效果,
为了列表中元素移动时的过渡效果,vue引入了v-move
过渡类名,如下的:.flip-list-move
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js">script>
<style>
.flip-list-move {
transition: transform 1s;
}
style>
<div id="flip-list-demo" class="demo">
<button v-on:click="shuffle">Shufflebutton>
<transition-group name="flip-list" tag="ul">
<li v-for="item in items" v-bind:key="item">
{{ item }}
li>
transition-group>
div>
<script>
new Vue({
el: '#flip-list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9]
},
methods: {
shuffle: function () {
this.items = _.shuffle(this.items)
}
}
})
script>
完整代码
上面讲的都是列表用css进行过渡,列表也可以用js代码进行过渡,如下:
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js">script>
<div id="staggered-list-demo">
<input v-model="query">
<transition-group
name="staggered-fade"
tag="ul"
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
>
<li
v-for="(item, index) in computedList"
v-bind:key="item.msg"
v-bind:data-index="index"
>{{ item.msg }}
li>
transition-group>
div>
<script>
new Vue({
el: '#staggered-list-demo',
data: {
query: '',
list: [
{ msg: 'Bruce Lee' },
{ msg: 'Jackie Chan' },
{ msg: 'Chuck Norris' },
{ msg: 'Jet Li' },
{ msg: 'Kung Fury' }
]
},
computed: {
computedList: function () {
var vm = this
return this.list.filter(function (item) {
return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
})
}
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0
el.style.height = 0
},
enter: function (el, done) {
var delay = el.dataset.index * 150
setTimeout(function () {
Velocity(
el,
{ opacity: 1, height: '1.6em' },
{ complete: done }
)
}, delay)
},
leave: function (el, done) {
var delay = el.dataset.index * 150
setTimeout(function () {
Velocity(
el,
{ opacity: 0, height: 0 },
{ complete: done }
)
}, delay)
}
}
})
script>
完整代码
To create a reusable transition, all you have to do is place a
or
组件的过渡也也可以不用,相当于一个壳子,壳子上带着过渡效果,你可以复用到别的地方
Yes, even transitions in Vue are data-driven! The most basic example of a dynamic transition binds the
name
attribute to a dynamic property.
由于过渡效果的实现都是在
or
组件上添加属性,那么这些属性的属性值根据不同条件也可以被指定不同的动态值。
这就是动态过渡的由来。让过渡更加灵活和随心所欲
更多Vue文档解读:《Vue Doc 笔记》