多个元素的过渡
- 对于原生标签可以使用
v-if/v-else
。需要注意的是当有相同标签名的元素切换时,需要通过key
特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在<transition>
组件中的多个元素设置key
是一个更好的实践。 - 在多个元素同时进入和离开过渡的时候,动画会混乱,可以用过渡模式避免这个问题。
in-out
: 新元素先进行过渡,完成之后当前元素过渡离开out-in
: 当元素先进行过渡,完成之后新元素过渡进入
- Demo
- 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中多个元素或组件的过渡</title>
<script src="http://vuejs.org/js/vue.js"></script>
<style>
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity .5s;
}
</style>
</head>
<body>
<div id="root">
<transition mode="out-in">
<div v-if="show" key="Hello">Hello World</div>
<div v-else key="Bye">Bye World</div>
</transition>
<button @click="handleClick">Toggle</button>
</div>
<script>
var vm = new Vue({
el: '#root',
data: {
show: true
},
methods: {
handleClick: function () {
this.show = !this.show
}
}
})
</script>
</body>
</html>
多个组件过渡
- 多个组件只需要动态组件切换即可,不需要
key
特性。 - Demo
- 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中多个元素或组件的过渡</title>
<script src="http://vuejs.org/js/vue.js"></script>
<style>
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity .5s;
}
</style>
</head>
<body>
<div id="root">
<transition mode="out-in">
<component :is="type"></component>
</transition>
<button @click="handleClick">Toggle</button>
</div>
<script>
Vue.component('child-one', {
})
Vue.component('child-two', {
})
var vm = new Vue({
el: '#root',
data: {
type: 'child-one'
},
methods: {
handleClick: function () {
this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
}
}
})
</script>
</body>
</html>
列表过渡
- 列表过渡需要使用
<transition-group>
组件,它的特点:- 不同于
<transition>
,它会以一个真实元素呈现:默认为一个<span>
。你也可以通过tag
特性更换为其他元素。 - 过渡模式不可用,因为我们不再相互切换特有的元素。
- 内部元素 总是需要 提供唯一的
key
属性值。
- 不同于
- Demo
- 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表过渡</title>
<script src="http://vuejs.org/js/vue.js"></script>
<style>
.list-complete-enter, .list-complete-leave-to {
opacity: 0;
transform: translateY(30px);
}
.item {
transition: all 1s;
display: inline-block;
margin-right: 10px;
}
</style>
</head>
<body>
<div id="root">
<button @click="add">Add</button>
<button @click="remove">Remove</button>
<transition-group mode="out-in" name="list-complete" tag="p">
<span v-for="item of list" :key="item" class="item">{{item}}</span>
</transition-group>
</div>
<script>
var vm = new Vue({
el: '#root',
data: {
list: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.list.length)
},
add: function () {
this.list.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.list.splice(this.randomIndex(), 1)
}
}
})
</script>
</body>
</html>
封装动画
- 将动画效果都封装到一个组件,其他组件使用时直接调用
- Demo
- 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<html lang="en">
<head>
<meta charset="UTF-8">
<title>封装动画</title>
<script src="http://vuejs.org/js/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
</head>
<body>
<div id="root">
<fade :show="show">
<div>Hello World</div>
</fade>
<fade :show="show">
<h1>Bye World</h1>
</fade>
<button @click="handleClick">Toggle</button>
</div>
<script>
Vue.component('fade', {
props: ['show'],
template: `
<transition @before-enter="handleBeforeEnter"
@enter="handleEnter"
@after-enter="hanldeAfterEnter">
<slot v-if="show"></slot>
methods: {
handleBeforeEnter: function (el) {
el.style.opacity = 0
el.style.transformOrigin = 'left'
},
handleEnter: function (el, done) {
el.textContent = 'Animation Start'
Velocity(el, {opacity: 1, fontSize: '1.5em'}, {duration: '300'})
Velocity(el, {fontSize: '1em'}, {complete: done})
},
hanldeAfterEnter: function (el) {
el.textContent = 'Animation End'
}
}
})
var vm = new Vue({
el: '#root',
data: {
show: true
},
methods: {
handleClick: function () {
this.show = !this.show
}
}
})
</script>
</body>
</html>