文档: https://cn.vuejs.org/v2/guide/transitions.html
八个钩子函数:
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="leaveCancelle 离开中取消
:css="false": 告诉vue这是js纯动画,不需要查找css,节省性能
name="slide": 结合css使用,js主要负责逻辑操作
<template>
<div>
<p>{{ load }}</p>
<hr>
<button class="btn btn-primary" @click="load = !load">点击</button>
<transition
@before-enter = "beforeEnter"
@enter = "enter"
@after-enter = "afterEnter"
@enter-cancelled = "enterCancelled"
@before-leave = "beforeLeave"
@leave = "leave"
@after-leave = "afterLeave"
@leave-cancelled = "leaveCancelled"
:css="false">
<div v-if="load" style="width: 100px; height: 15px; background-color : #eaff56; border-radius : 0 10px 10px 0;"></div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
load : false,
divWidth: 0,
}
},
methods: {
beforeEnter(el) {
// console.log("beforeEnter")
this.divWidth = 0;
el.style.width = this.divWidth + "px";
},
enter(el, done) {
// console.log("enter")
// done()
// done是个函数 执行完才会进行下一步
let round = 1;
const timer = setInterval( () => {
el.style.width = (this.divWidth + round * 10) + "px";
round++;
// console.log(round)
if(round > 50) {
clearInterval(timer);
done();
}
},20 )
},
afterEnter(el) {
// console.log("afterEnter")
el.style.width = "500px"
},
enterCancelled(el) {
console.log("enterCancelled")
// 动画取消的时候执行
// 比如还没淡入完成就开始淡出的时候
// 可以直接写在css上
},
beforeLeave(el) {
// console.log("beforLeave")
el.style.width = "500px";
this.divWidth = 500;
},
leave(el, done) {
// console.log("leave")
// done()
let round = 1;
const timer = setInterval( () => {
el.style.width = (this.divWidth - round * 10) + "px";
round++;
// console.log(round)
if(round > 50) {
clearInterval(timer);
done();
}
},20 )
},
afterLeave(el) {
// console.log("afterLeave")
this.divWidth = 0;
},
leaveCancelled(el) {
// console.log("leaveCancelled")
}
}
}
</script>
<style>
</style>
![v2-cd2bc998dfd3ca00382f12ddc033c3d2_b.gif](https://i-blog.csdnimg.cn/blog_migrate/643bb59c1aea810ffb21a65a071044b3.gif)
切换组件的动画
动态切换组件动画
使用一个button按钮来控制组件的切换,使用:is绑定动态的组件,使用transition来做就可以了
我引入来animation库
<template>
<div>
<p>{{ load }}</p>
<hr />
<button class="btn btn-primary" @click="load = !load">点击</button>
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
:css="false"
>
<div
v-if="load"
style="width: 100px; height: 15px; background-color : #eaff56; border-radius : 0 10px 10px 0;"
></div>
</transition>
<hr>
<button class="btn btn-primary" @click=" selectComponent == 'app-alert-danger' ? selectComponent = 'app-alert-success' : selectComponent = 'app-alert-danger'">切换组件</button>
<br><br>
<transition
enter-active-class="animated rollIn"
leave-active-class="animated rollOut"
mode="out-in">
<component :is="selectComponent"></component>
</transition>
</div>
</template>
<script>
import alertDanger from "./alertDanger"
import alertSuccess from "./alertSuccess"
export default {
data() {
return {
load: false,
divWidth: 0,
selectComponent: "app-alert-danger"
};
},
components: {
"app-alert-danger" : alertDanger,
"app-alert-success" : alertSuccess,
// 带上-,防止第三方库冲突
},
methods: {
beforeEnter(el) {
// console.log("beforeEnter")
this.divWidth = 0;
el.style.width = this.divWidth + "px";
},
enter(el, done) {
// console.log("enter")
// done()
// done是个函数 执行完才会进行下一步
let round = 1;
const timer = setInterval(() => {
el.style.width = this.divWidth + round * 10 + "px";
round++;
// console.log(round)
if (round > 50) {
clearInterval(timer);
done();
}
}, 20);
},
afterEnter(el) {
// console.log("afterEnter")
el.style.width = "500px";
},
enterCancelled(el) {
console.log("enterCancelled");
// 动画取消的时候执行
// 比如还没淡入完成就开始淡出的时候
// 可以直接写在css上
},
beforeLeave(el) {
// console.log("beforLeave")
el.style.width = "500px";
this.divWidth = 500;
},
leave(el, done) {
// console.log("leave")
// done()
let round = 1;
const timer = setInterval(() => {
el.style.width = this.divWidth - round * 10 + "px";
round++;
// console.log(round)
if (round > 50) {
clearInterval(timer);
done();
}
}, 20);
},
afterLeave(el) {
// console.log("afterLeave")
this.divWidth = 0;
},
leaveCancelled(el) {
// console.log("leaveCancelled")
}
}
};
</script>
<style>
</style>
![v2-519958d9a36d7550e4279b0eadde647a_b.gif](https://i-blog.csdnimg.cn/blog_migrate/c70cc145e3790fda973afbb7ae34221a.gif)
需求: 做一个动画的列表过渡
transition-group
要求: 做一个按钮,点击按钮在列表中随机添加一个数,点击列表中的li,删除该li
transition-group和transition的区别:
transition-group会生成一个真实的dom,默认span,可以使用tag属性来修改,还可以添加class;
transition不会;
transition-group需要key值才能用
<template>
<div>
<p>{{ load }}</p>
<hr />
<button class="btn btn-primary" @click="load = !load">点击</button>
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
:css="false"
>
<div
v-if="load"
style="width: 100px; height: 15px; background-color : #eaff56; border-radius : 0 10px 10px 0;"
></div>
</transition>
<hr>
<button class="btn btn-primary" @click=" selectComponent == 'app-alert-danger' ? selectComponent = 'app-alert-success' : selectComponent = 'app-alert-danger'">切换组件</button>
<br><br>
<transition
enter-active-class="animated rollIn"
leave-active-class="animated rollOut"
mode="out-in">
<component :is="selectComponent"></component>
</transition>
<br><br>
<hr>
<button class="btn btn-primary" @click="addItem">添加列表</button>
<transition-group tag="ul" class="list-group" name="slide">
<li class="list-group-item"
v-for="(list, index) in lists"
@click="removeItem(index)"
style="cursor: pointer"
:key="list">
{{ list }}</li>
</transition-group>
<ul class="list-group">
</ul>
</div>
</template>
<script>
import alertDanger from "./alertDanger"
import alertSuccess from "./alertSuccess"
export default {
data() {
return {
load: false,
divWidth: 0,
selectComponent: "app-alert-danger",
lists: [1, 2, 3, 4, 5]
};
},
components: {
"app-alert-danger" : alertDanger,
"app-alert-success" : alertSuccess,
// 带上-,防止第三方库冲突
},
methods: {
addItem() {
const pos = Math.floor(Math.random() * this.lists.length);
// 在当前列表中随机找一个行前添加
this.lists.splice(pos, 0, this.lists.length + 1)
// 在列表中有几个数,就添加比几个数多1的数
},
removeItem(index) {
this.lists.splice(index, 1)
// 切割1项
},
beforeEnter(el) {
// console.log("beforeEnter")
this.divWidth = 0;
el.style.width = this.divWidth + "px";
},
enter(el, done) {
// console.log("enter")
// done()
// done是个函数 执行完才会进行下一步
let round = 1;
const timer = setInterval(() => {
el.style.width = this.divWidth + round * 10 + "px";
round++;
// console.log(round)
if (round > 50) {
clearInterval(timer);
done();
}
}, 20);
},
afterEnter(el) {
// console.log("afterEnter")
el.style.width = "500px";
},
enterCancelled(el) {
console.log("enterCancelled");
// 动画取消的时候执行
// 比如还没淡入完成就开始淡出的时候
// 可以直接写在css上
},
beforeLeave(el) {
// console.log("beforLeave")
el.style.width = "500px";
this.divWidth = 500;
},
leave(el, done) {
// console.log("leave")
// done()
let round = 1;
const timer = setInterval(() => {
el.style.width = this.divWidth - round * 10 + "px";
round++;
// console.log(round)
if (round > 50) {
clearInterval(timer);
done();
}
}, 20);
},
afterLeave(el) {
// console.log("afterLeave")
this.divWidth = 0;
},
leaveCancelled(el) {
// console.log("leaveCancelled")
}
}
};
</script>
<style>
.slide-enter {
opacity: 0;
transform: translateY(20px)
}
.slide-enter-active {
transition: opacity 1s;
animation: slide-in 1s ease-out;
}
.slide-enter-to {
transform: translateY(0px)
}
.slide-leave {
transform: translateY(0px)
}
.slide-move {
transition: transform 1s;
}
.slide-leave-active {
transition: opacity 1s;
animation: slide-out 1s ease-out;
position: absolute;
/* 离开的时候脱离文档流 */
}
.slide-leave-to {
opacity: 0;
transform: translateY(20px)
}
/* 进入轨迹 */
@keyframes slide-in {
from{
transform: translateY(20px);
}
to{
transform: translateY(0);
}
}
/* 离开轨迹 */
@keyframes slide-out {
from{
transform: translateY(0);
}
to{
transform: translateY(20px);
}
}
</style>
![v2-2891de7849177c66cc5bdb5bcaf2fbc9_b.gif](https://i-blog.csdnimg.cn/blog_migrate/34c3894d7993cd3517cea77b17ed2930.gif)