<Transition>
为我们提供动画或者过渡过程中的钩子函数,我们可以以组件事件的方式来监听它。
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled"
>
<!-- ... -->
</Transition>
动画和过渡执行的每一个时刻都会有一个构造函数会被调用,我们来看一下这些钩子函数都会在什么时候被执行。
before-enter
在元素被插入到 DOM 之前被调用。
enter
在元素被插入到 DOM 之后的下一帧被调用。
after-enter
当进入过渡完成时调用。
enter-cancelled
当进入过渡在完成之前被取消时调用。
before-leave
在 leave 钩子之前调用。
leave
在离开过渡开始时调用。
after-leave
在离开过渡完成、且元素已从 DOM 中移除时调用。
leave-cancelled
仅在 v-show 过渡中可用。
先准备一下基础代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>document</title>
</head>
<script src="https://unpkg.com/vue@next"></script>
<body>
<div id="app"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
message: "hello world!",
isShow:false
}
},
methods: {
handelClick(){
this.isShow=!this.isShow
}
},
template: `
<Transition>
<div v-if="isShow" class="div">{{message}}</div>
</Transition>
<button @click="handelClick">启动/关闭</button>
`
})
const vm = app.mount("#app")
</script>
<style>
.div{
position: absolute;
left: 0;
top: 100px;
}
</style>
</html>
JS实现动画效果
利用这几个钩子函数我们可以自己通过js来执行动画,但是在我们采用js来驱动动画时,我们需要通过设置<Transition>
组件属性:css="false"
,让它禁止采用css动画。
<Transition
...
:css="false"
>
...
</Transition>
在使用js执行动画时我们也可以采用第三方动画库来执行,比如GreenSock
Anime.js
Motion One
等等。
那么,我们这里只是给大家做个简单的演示,我们就简单用js在实现一个移动动画。
我们先给来hello world
div元素设置一个position定位,方便我们后面操控left和top坐标。
<div v-if="isShow" class="div">{{message}}</div>
<style>
.div{
position: absolute;
left: 0;
top: 100px;
}
</style>
好了,然后我们使用before-enter
钩子函数在元素被插入到 DOM 之前设置一个动画开始前的默认值,给元素left默认设置成0。
onBeforeEnter(el){ //他接收一个dom元素
el.style.left="0"
},
然后在enter
钩子函数里来编写js动画。在这个方法里面我们来使用setInterval
每20毫秒让元素向左边移动1px,直到移动到100px时停止动画,enter
这个方法它接受两个参数dom
元素 和 done
回调方法。
在需要停止动画的时候,我们清除一下setInterval
然后还需要调用一下 done
方法以此来告诉VUE我们的动画运行结束了
onEnter(el, done){
let moveTimer = setInterval(() => {
let offsetX = parseInt(el.offsetLeft)
offsetX++
el.style.left=offsetX+'px'
if(offsetX>=100){
//动画只想结束了
done()
clearInterval(moveTimer)
}
},20);
},
最后在onAfterEnter
钩子函数里面我们可以监听到动画执行结束,我们可以在这里面处理一下动画结束后的业务逻辑,这里需要注意的是,enter
方法里面动画执行完成之后必须调用done
方法告诉vue动画执行完成了onAfterEnter
函数才会被调用。
onAfterEnter(el){
console.log("入场动画结束")
},
Transition组件现在的样子。
template: `
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
>
<div v-if="isShow" class="div">{{message}}</div>
</Transition>
<button @click="handelClick">启动/关闭</button>
`
好搞完了这些,我们就可以来运行看一下效果了。
离场动画的编写
我们写好了入场动画,我们可以按照相同方式来写离场动画。主要用到before-leave
leave
after-leave
这三个钩子函数。运行方式以及接收的参数和入场动画是一致的
编写的所有代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>document</title>
</head>
<script src="https://unpkg.com/vue@next"></script>
<body>
<div id="app"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
message: "hello world!",
isShow:false
}
},
methods: {
handelClick(){
this.isShow=!this.isShow
},
onBeforeEnter(el){
el.style.left="0"
},
onEnter(el, done){
let moveTimer = setInterval(() => {
let offsetX = parseInt(el.offsetLeft)
offsetX++
el.style.left=offsetX+'px'
if(offsetX>=100){
//动画只想结束了
done()
clearInterval(moveTimer)
}
},20);
},
onAfterEnter(el){
console.log("入场动画结束")
},
onBeforeLeave(el){
el.style.left = "100px"
},
onLeave(el,done){
let moveTimer = setInterval(() => {
let offsetX = parseInt(el.offsetLeft)
offsetX--
el.style.left = offsetX + 'px'
if (offsetX <=0) {
//动画只想结束了
done()
clearInterval(moveTimer)
}
}, 20);
},
onAfterLeave(el){
console.log("离场动画结束")
}
},
template: `
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
>
<div v-if="isShow" class="div">{{message}}</div>
</Transition>
<button @click="handelClick">启动/关闭</button>
`
})
const vm = app.mount("#app")
</script>
<style>
.div{
position: absolute;
left: 0;
top: 100px;
}
</style>
</html>
好了, 那么这节课我们就到这里结束了。