一、说明
前两种都是一个完整动画,也无法实现半场动画。
需要实现半场动画,只需要入场动画。
可以在属性中声明JavaScript 钩子,即v-on绑定事件指向methods中函数,按需要声明。
<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 结合使用时
// 回调函数 done 是可选的
//动画效果(最终位置、中间过渡)
enter: function (el, done) {
// ...
done()
},
//动画完成之后会调用
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// 离开时
// --------
beforeLeave: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}
动画钩子函数的第一个参数el
表示要执行动画的那个DOM元素,原生JS DOM对象。
- 当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
-
done()
其实就是afterEnter
和afterLeave
的引用。
二、实例
点击按钮后出现红点掉落消失的半场效果。
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<style>
.ball{
width: 15px;
height: 15px;
background-color: red;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="加入购物车" @click="flag = !flag" />
<transition v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
},
methods:{
beforeEnter(el){ //动画入场前,设置小球的起始位置
el.style.transform = "translate(0,0)";
},
enter(el,done){ //动画效果
//TODO 这里没有实际作用,但是不调用,没有动画效果?
//认为这个会强制刷新动画效果
el.offsetWidth; //offsetHeight...等
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease";
done(); //动画完成之后会立即执行消失,其实就是afterEnter函数的引用
},
afterEnter(el){ //动画结束后
this.flag = !this.flag; //隐藏了小球,但是小球位置还是在结束位置
//下次点击会执行下次动画的生命周期,即beforeEnter开始,又会回到起始位置
}
}
});
</script>
</body>
</html>
- 在
enter
钩子函数中一定要调用一下el.offsetWidth;
,不然不会有动画中间效果,只有开始和结束状态。 - 虽然动画结束后只让小球消失了而没有初始化小球位置,这不影响。下次点击会执行新的动画生命周期,即会执行
beforeEnter
重新初始化了小球位置。
三、修改flag标识的作用
上面实例中,我们使用flag
属性作为标识符,来表示动画的切换。
Vue把一个完整的动画,使用钩子函数,拆分成了两部分,flag值的改变表示了上半场动画和下半场动画。
前半场刚开始,flag = false -> true
;后半场结束时应该flag = true -> false
,但此处没有后半场动画(只是半场动画),则在afterEnter
中执行,控制小球隐藏,并且直接跳过后半场动画。
- 所以说,如果最后没有改变
flag
为false
让元素消失(例如直接在afterEnter
中改变元素opacity
),下次再点进行取非就是flag=ture->false
,已经不是前半场动画的逻辑了,这样做是不行的后面就不生效了。
错误:
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<style>
.ball{
width: 15px;
height: 15px;
background-color: red;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="加入购物车" @click="flag = !flag" />
<transition v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
},
methods:{
beforeEnter(el){ //此时flag=false
el.style.transform = "translate(0,0)";
},
enter(el,done){ //此时flag取非=true
el.offsetWidth;
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease";
done();
},
afterEnter(el){ //动画结束后
el.style.opacity=0; //没有让flag=false让动画结束,而是直接改变了opacity,下次动画入场过程就错误了
}
}
});
</script>
</body>
</html>
网友评论