Vue2.0 vue-transition探索

这里是官方文档:http://cn.vuejs.org/v2/guide/transitions.html

一、开始
我们可以随便在一个 vue 文件下写上(一个模板文件下):

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<template>
<div id="movie">
<button @click="showMenu" class="btn">{{text}}</button>
<!--动画部分-->
<transition name="move">
<div class="menu" v-show="show">
<div class="inner inner-1">1</div>
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: false
};
},
methods: {
showMenu() {
this.show = !this.show;
}
},
computed: {
text() {
return this.show ? '收' : '开';
}
}
};
</script>
<style>
#movie{
margin-top:10px;
}
.btn{
position: fixed;
top:60px;
left:50%;
z-index:10;
width:50px;
height:50px;
line-height:50px;
border-radius: 50%;
border:none;
outline:none;
color:#fff;
font-size:18px;
background:orange;
}
.inner-1{
display: inline-block;
position:absolute;
width:30px;
height:30px;
line-height:30px;
border-radius:50%;
background: red;
text-align:center;
color:#fff;
transition:all 0.4s;
left:-50px;
top:20px;
}
.menu{
position:fixed;
top:60px;
left:50%;
width:50px;
height:50px;
border-radius:50%;
transition:all 0.7s linear;
}
/*上面主要都是样式代码*/
.move-enter-active > .inner-1{
transform: translate3d(0,0,0);
}
.move-enter > .inner-1,
.move-leave-active >.inner-1{
transition-timing-function: ease-in-out ;
transform:translate3d(60px,0,0) ;
}
</style>

再点开这个页面,可以看到一个最简单的过渡效果:
start.gif
这里,我把enter理解为动画的起始状态leave-active理解为返回最终状态(这个过渡效果类似 CSS3 的 animation)

其实也可以直接用 CSS3 的 animation,只需要做如下修改:

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<template>
<div id="movie">
<div id="example-2">
<button @click="showMenu" class="btn">{{text}}</button>
<transition name="bounce">
<p style="padding-left:50px" v-if="show">Look at me!</p>
</transition>
</div>
</div>
</template>
<script>
export default {
data() {
return {
show: false
};
},
methods: {
showMenu() {
this.show = !this.show;
}
},
computed: {
text() {
return this.show ? '逝' : '现';
}
}
};
</script>
<style>
#movie{
margin-top:10px;
}
.btn{
position: fixed;
top:60px;
left:50%;
z-index:10;
width:50px;
height:50px;
line-height:50px;
border-radius: 50%;
border:none;
outline:none;
color:#fff;
font-size:18px;
background:orange;
}
.bounce-enter-active {
animation: bounce-in 2s;
}
.bounce-leave-active {
animation: bounce-out 2s;
}
@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);
}
}

</style>

运行看下效果:
startCSS.gitstart
其实就 vue 帮你加了个 class 又自动帮你移除了
二、多个组件过渡
组件的过渡可以痛通过绑定选中值实现

这里我们再修改下 Vue 文件:

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
<template>
<div id="movie">
<div class="radio">
<input type="radio" id="one" value="v-a" v-model="view">
<label for="one">A</label>
<input type="radio" id="two" value="v-b" v-model="view">
<label for="two">B</label>
</div>
<div class="show">
<transition name="component-fade" mode="out-in">
<component :is="view"></component>
</transition>
</div>
</div>
</template>
<script>
export default {
data() {
return {
view: 'v-a',
picked: 'one'
};
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
};
</script>
<style>
#movie{
margin-top:25px;
width:100%;
height:200px;
display:flex;
flex-direction: column;
align-items: center;
}
.component-fade-enter-active .conpoment-fade-leave-active{
opacity: 1;
transition: all 0.5s ease;
}
.component-fade-enter, .component-fade-leave-active {
opacity: 0;
}
</style>

这样我们就可以在选择的数据变化时实现简单的过渡:
script.gif
三、JavaScript 钩子
script 钩子其实就是一一设定绑定状态的变化,设置相对应的过渡效果,看下例子:
html

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<div id="movie">
<img class="target" src="./basket.png"></img>
<transition v-for="ball in balls" name="shooting" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<!--外层做纵向动画-->
<div class="ball" v-show="ball.show">
<!--内层做横向动画-->
<div class="inner"></div>
</div>
</transition>
<img class="shoot" @click="shoot($event)" src="./player.png"></img>
</div>
******script*****
data() {
return {
balls: [
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
}
],
dropBalls: []
};
},
methods: {
shoot(el) {
var balls = this.balls;
for (let i in balls) {
let ball = balls[i];
if (!ball.show) {
ball.show = true;
ball.el = el.target;
this.dropBalls.push(ball);
return;
}
}
},
beforeEnter:function(el) {
let count = this.balls.length;
while (count--) {
let ball = this.balls[count];
if (ball.show) {
let rect = ball.el.getBoundingClientRect();
let left = rect.left ;
console.log(el);
let top = -(window.innerHeight - rect.top - 520);
el.style.display = '';
el.style.webkitTransform = `translate3d(0,${top}px,0)`;
el.style.transform = `translate3d(0,${top}px,0)`;
let inner = el.getElementsByClassName('inner')[0];
inner.style.webkitTransform = `translate3d(${left}px,0,0)`;
inner.style.transform = `translate3d(${left}px,0,0)`;
}
}
},
enter:function(el) {
/* eslint-disable no-unused-vars */
let refresh = el.offsetHeight;
this.$nextTick(() => {
el.style.webkitTransform = 'translate3d(0,0,0)';
el.style.transform = 'translate3d(0,0,0)';
let inner = el.getElementsByClassName('inner')[0];
inner.style.webkitTransform = 'translate3d(0,0,0)';
inner.style.transform = 'translate3d(0,0,0)';
});
},
afterEnter:function(el) {
let ball = this.dropBalls.shift();
if (ball) {
ball.show = false;
el.style.display = 'none';
}
}
}

其实就是设置相应的变化位置,完成变化,最后看下效果:
script.gif

四、表单过渡(transition-group)
其实这个 transition-group 相当于给每一个元素添加一个 transition,但需要指定唯一的标识 key,看下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div id="movie">
<div id="list-demo" class="demo">
<button v-on:click="add">Add</button>
<transition-group name="list" tag="ul">
// key值为item
<li v-for="(item,index) in items" :key="item" class="list-item" @click="deleteShow(index)">{{ item.text }}
// 给删除按钮再加个动画
<transition name="move">
<button class="deleteButton" v-show="item.show" @click="deleteItem(index)">删除</button>
</transition>
</li>
</transition-group>
</div>
</div>
</template>

看上面的代码,其实就是和普通的 transition 是差不多的,只需理解为给每一个元素添加一个 transition 就行了,再看看样式代码:

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
#movie{
margin-top:25px;
width:100%;
height:200px;
display:flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
position:relative;
}
button{
left:50%;
margin-left:-50px;
position:relative;
}
.deleteButton {
position:absolute;
width:50px;
height:30px;
bottom:0;
left:300px;
}
.list-item {
position:relative;
display: inline-block;
width:300px;
height:30px;
margin:5px 40px;
background:lightgrey;
transition: all 0.5s linear;
}
/*进入的初始状态*/
.list-enter, .list-leave-active {
opacity:0;
transform: translateX(-300px);
}
/*列表平滑过渡*/
/*离开的状态*/

.list-leave-active {
transform: translateX(-300px);
position:absolute
}
.move-enter,.move-leave-active{
transform: translate3d(50px,0,0);
opacity: 0;
}
.move-enter-active,.move-leave-active{
opacity: 1;
transition: all 0.2s linear;
}
</style>

看下结果,实现了一个最简单transition-group
transition-group.gif
最主要的是理解经历的状态以及状态的变化,添加相应的样式,就可以做出想要的效果了