这篇解决正常的动画进入,为什么称为正常进入呢,这是和首次渲染的比较。
首次渲染和正常渲染的区别
第15篇文章中提到,组次首次进入就缓动是一个特例,但首次进入这个字面意思就比较费解,下面解释一下:
首次进入
列如下面的代码:
<transition>
<div></div>
</transition>
第一创建transition,由于它包裹的“儿子”DOM是现成的,所以直接顺带把它挂上去了,也即创建transition的同时将DOM也挂上去了,这称为首次进入。
第二种情况
<transition>
<div v-if="show"></div>
</transition>
开始建transition,由于开始show为false,所以父亲没有儿子,它自己建好了。过一会我们点击按钮,v-if为真,那么div就挂上来了,但此时它父亲早已建好,这种状态就称为正常的显隐。
也就是说,transition是先创建好的,“儿子”是后面某个时机挂载上去的。通过这么对比,我们就清楚了,为什么首次进入只会执行一次,由于transition本身的创建只有一次,虽然它内部的DOM可以换来换去,但它本身只创建了一次。
目前我们可以做个总结,首次动画和正常动画是以transition这个组件的创建与否做为参照标准的。
第15篇就是讲第一种情况,而本篇是写第二种情况。
缓动四大件
虽然动画DOM是后面加进去的,但它同样遵循缓动四件套,即开始状态、结束状态、缓动规则和动作触发。
这里Vue有两套查找规则,第一种是默认的class,第二种是命名的class。
默认的css和命名的css
如果不明确指定,Vue就会在css定义中找下面三个class:
v-enter
v-enter-active
v-enter-to
如果transition具有name属性,那么就会使用name开头的class样式,相当于给用户一个命名的机会,动画的三个class命名规则如下:
${name}-enter
${name}-enter-active
${name}-enter-to
列如:
<transition name="box">
<div class="box" v-if="show"></div>
</transition>
在这个代码中,transition有一个name属性,那么Vue就会在CSS中查找下面的样式:
box-enter
box-enter-active
box-enter-to
缓动的触发动作
和第15文章一样,触发动作也是在下一帧回调中执行的。
实验:显示DOM时,让它从右侧滑入
第一看效果图:

需求:在DOM显示时,让它先从偏离X 100px开始,然后经过缓动到达div正常位置。
代码如下:

分析:这个代码发生一个重大问题,就是.box-enter-to即结束状态不见了!!但好在,我们在说缓动四件套的时候也提到过,状态是可选的,也就是说开始状态和结束状态的两者任一是可选的。
目前的情况是有开始,没有结束。那么状态差值是怎么产生的呢?
这个问题在第15篇文章中没有提到,那么这个问题是怎么解决呢?
问题是这样的:
//第一次渲染
增加.box-enter
增加.box-enter-active
//第二次渲染前的回调
删除.box-enter
增加.box-enter-to
可以看到在回调中删除.box-enter开始状态,除了是清理,还有一个重大的功能就是应付我们这个问题的,也就是说如果没有结束状态,它把开始状态删除了,就是一下又回到原始状态了,那么原始状态和开始状态之间比较就有差值了,就好比你先把弹簧拉长(开始),然后再让它回到原始位置(结束),超级精彩!!
同样,我们还可以做成没有开始,只有结束,原理是一样。
最后,transition有了一个具体的name,那么Vue就会查找以${name}-打头的CSS。
离开动画
组件创建之后,也可能会销毁。目前我们再看下离开时的动画,代码如下:

分析:和正常显示动画一样,不过以${name}-leave开头,原理几乎一样,这里不再赘述。
总结
这篇主要说明了下面几个重大问题:
- 首次缓动和正常缓动的区别。
- 正常缓动的命名CSS
- 离开缓动的使用
完整的实验代码
代码完整演示了正常进入缓动和退出缓动
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
width: 200px;
height: 100px;
background: #673ab7;
color: white;
text-align: center;
line-height: 100px;
margin: 20px;
}
.box-enter {transform: translateX(100px);}
.box-enter-active {transition: all 1s ease;}
.box-leave-active{transition: all 1s ease;}
.box-leave-to{transform: translateX(-100px);}
</style>
</head>
<body>
<div id="app">
<button @click="show=!show">
{{show?'隐藏动画组件':'显示动画组件'}}
</button>
<transition name="box">
<div class="box" v-if="show"></div>
</transition>
</div>
<script src="../vue.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
show: false
}
}
})
</script>
</body>





