vue中的过渡与动画
过滤
把需要添加动画效果的DIV放到transition标签
之后就会发生以下3个步骤
-
自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名(等下要写的6个类名)。
-
如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
-
如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的
nextTick
概念不同)
类名
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to
: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter
被移除),在过渡/动画完成之后移除。
v-leave
: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to
: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave
被删除),在过渡/动画完成之后移除。
插入
其实是看完了文档我也是一脸懵逼,看到这里其实有很多问题就出来了,下面我们一一列举一一解答
- 什么是定义进入/离开过渡
- 什么是在元素被插入之前,这个插入是插入到什么地方
- 当我们自身元素的css样式和v-enter,v-enter-to,v-leave,v-leave-to会出现重复吗?,是会覆盖还是不会覆盖,而且覆盖是谁覆盖谁,是自身的样式权重高呢,还是v-enter...呢?
- v-if和v-show的区别
1.什么是定义进入/离开过渡
进入过渡:元素显示的过程
离开过渡:元素离开的过程
以前我理解这个就是有一个地方无法理解,明明不管元素是显示还是隐藏他们都是一个过渡过程,那么其实他们(显示过程或离开过程)都是代表的进入过渡,对吧,我以前一直以为是文档表达的不清楚,但是后来我发现我自己太天真了,嘿嘿/斜眼笑。
2.什么是在元素被插入之前,这个插入是插入到什么地方
为什么我会有这个问题呢?因为v-if和v-show的区别大家应该都知道v-if是通过DOM的增删改变的显示隐藏,但是v-show呢?他可是通过display来显示和隐藏的啊,如果你说你只可以用v-if那是插入还差不多,但是你如果用的是v-show也可以达到效果,但是那你的文档的定义感觉有点问题啊是把?后来我发现我天真了,为什么呢?因为其实我们知道除了DOM树,还有一个浏览器的--渲染树,什么是渲染树呢?这里有我找的一篇文章,渲染树其实就是一个依赖DOM树,先有DOM树,再根据DOM去生成浏览器是渲染树,再文章中说了一句很关键的话:如果元素的display属性被设置成了none,或者如果元素的子孙继承了display:none,renderer不会被创建。节点的子类和display属性一起决定为该节点创建什么样的渲染器,说明了其实就算是v-show为false他的DOM依然在,但是也是是单单在DOM树上,在浏览器的渲染树上是不存在的所以才有了插入的在一个说法,并且第一个问题的进入/离开也有了很好的介绍,就是进入离开渲染树
3.当我们自身元素的css样式和v-enter,v-enter-to...是否会发出重复呢
-
重复是否会出错
-
发生覆盖,那么谁覆盖谁
这里我建议当我们要过渡一个元素的属性的时候,我们不要再这个元素上定义这个属性值
案例
过渡改变div的高度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.js"></script>
<style>
.box{
border: 1px solid saddlebrown;
background-color: brown;
}
.box p{
margin: 0;
height: 156px;
border: 1px solid saddlebrown;
}
.bounce-enter-active,.bounce-leave-active {
transition: all 1s ease;
}
.bounce-leave,.bounce-enter-to{
height: 156px;
}
.bounce-enter,.bounce-leave-to {
height: 0;
color: chartreuse;
}
</style>
</head>
<body>
<div id="example-2">
<button @click="show = !show">Toggle show</button>
<transition name="bounce">
<div class="box" v-show='show'>
<p>我的高度我156px;</p>
</div>
</transition>
</div>
<script>
new Vue({
el: '#example-2',
data: {
show: false
}
})
</script>
</body>
</html>
这个案例是正常的情况,但是你们是否有注意到其实我这里的高度是设置再v-enter上面的?因为当我们设置再v-enter下面的时候就会出现问题?其实答案很简单就是样式发生了覆盖,导致高度一直都是156px还怎么过渡对吧,覆盖是根据css文件中样式书写的顺序,不是HTML上的顺序,大家可以去放下去试一下
<style>
/* .box p{
margin: 0;
height: 156px;
border: 1px solid saddlebrown;
} */
.bounce-enter-active,.bounce-leave-active {
transition: all 1s ease;
}
.bounce-leave,.bounce-enter-to{
height: 156px;
}
.bounce-enter,.bounce-leave-to {
height: 0;
color: chartreuse;
}
.box{
border: 1px solid saddlebrown;
background-color: brown;
height: 156px;
}
</style>
也可以去打开F12去看样式中有被下划线,因为替代而被下划的样式;
4.v-if和v-show的区别
再vue中的javaScriot钩子函数(enter等下面的那些)监听的是浏览器渲染树中结构,所以v-if和v-show的区别其实是
v-if:先生成DOM树浏览器渲染树中的那个结构也是新生成的;
v-show:是修改了DOM树,浏览器中的渲染树是去更新渲染树
动画
为什么这里不用谢v-enter呢? 我们想一下其实我们动画里面是包含了开始状态和结束状态的,我们需要的只是执行那个动画,不用想过渡一样定义过渡的开始和结束值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue中css动画的原理</title>
<script src="./node_modules/vue/dist/vue.js"></script>
<style>
@keyframes bounce {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
/* .fade-enter-active和.fade-leave-active代表一直都在的那个时间点 */
.fade-enter-active {
transform-origin: left center;
/* 这里写这个因为div太宽了 */
animation: bounce 1s;
}
.fade-leave-active {
transform-origin: left center;
animation: bounce 1s reverse;
}
</style>
</head>
<body>
<div id="root">
<transition name="fade">
<div v-if="show">hello world</div>
</transition>
<button @click="click">切换</button>
</div>
<script>
var root = new Vue({
el: '#root',
data: {
show: true
},
methods: {
click: function () {
this.show = !this.show;
}
}
})
</script>
</body>
</html>
这里你会发现动画没写v-enter和v-leave-to为什么呢?
因为他是动画啊它不需要像过滤一样有初始和结束的差别来判断,他只需要知道什么时候执行v-enter-active 和v-leave-active
再执行里面的语句就可以了
JavaScript钩子函数
除了用CSS过渡的动画来实现vue的组件过渡,还可以用JavaScript的钩子函数来实现,在钩子函数中直接操作DOM。我们可以在属性中声明以下钩子:
<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) {
// ...
},
// 设置过渡进入完成时的组件状态
enter: function (el, done) {
// ...
done()
},
// 设置过渡进入完成之后的组件状态
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// 过渡离开
// 设置过渡离开之前的组件状态
beforeLeave: function (el) {
// ...
},
// 设置过渡离开完成时地组件状态
leave: function (el, done) {
// ...
done()
},
// 设置过渡离开完成之后的组件状态
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}