Vue中不同的组件如果进行不同的动画效果
在以前进行vue开发的时候,我们经常会使用
<transition>
组件进行动画的切换,在使用这个组件组件的时候,遇到过一个问题,就是如果动态赋值的组件进行不同的动画效果
针对上面的问题,我做了如下的测试
- 首先,我使用了animate.css来进行动画效果,当然,大家也可以使用自己定义的动画
- 其实,在每个要定义动画的组件里面,添加
<transition>
话不多说,看代码
<template>
<transition enter-active-class=" animated fadeInLeftBig" leave-active-class=" animated fadeOutLeftBig">
<div class="movieList">
<movie-item></movie-item>
<movie-item></movie-item>
<movie-item></movie-item>
</div>
</transition>
</template>
<script>
import movieItem from "@/components/movieItem.vue";
export default {
name:"movieList",
data(){
return {
}
},
components:{
movieItem
}
}
</script>
<style lang="scss" scoped>
.movieList{
position: absolute;
left: 0px;
top: 0px;
width: 100%;
}
</style>
说明:上面的代码里面,我指定了enter-active-class与levae-active-class来设置进入与离开的动画
接下来,我们再来看一下另一个组件
<template>
<transition enter-active-class=" animated fadeInRightBig" leave-active-class=" animated fadeOutRightBig">
<div class="cinemalList">
<movie-item></movie-item>
<movie-item></movie-item>
<movie-item></movie-item>
</div>
</transition>
</template>
<script>
import movieItem from "@/components/movieItem.vue";
export default {
name:"cinemalList",
data(){
return {
}
},
components:{
movieItem
}
}
</script>
<style lang="scss" scoped>
.cinemalList{
position: absolute;
left: 0px;
top: 0px;
width: 100%;
}
</style>
大家可能已经发现了,我这里的动画效果和上面的动画效果上反向的,没错,我要的就是这效果
接下来,引入这两个组件
<template>
<div class="index">
<header class="header">
猫眼电影
</header>
<ul class="topNav">
<li :class="{active:pageType==0}" @click="pageType=0"><a href="#">影片</a></li>
<li :class="{active:pageType==1}" @click="pageType=1"><a href="#">影院</a></li>
</ul>
<div class="content">
<movie-list v-show="pageType==0"></movie-list>
<cinemal-list v-show="pageType==1"></cinemal-list>
</div>
</div>
</template>
<script>
import movieList from "@/components/movieList.vue";
import cinemalList from "@/components/cinemalList.vue";
export default {
name:"index",
data(){
return{
pageType:0
}
},
components:{
movieList,cinemalList
}
}
</script>
<style lang="scss" scoped>
@import "../scss/common.scss";
.index{
position: absolute;
width: 100%;
height: 100%;
left: 0px;
top: 0px;
.header{
height: $headerHeight;
@include flexbox(){
justify-content: center;
align-items: center;
}
font-size: 18px;
background-color: $primaryColor;
color: white;
}
.topNav{
@include flexbox(){
justify-content: center;
align-items: center;
};
li{
width: 50%;
height: 40px;
border-bottom: 3px solid lightgray;
>a{
text-decoration: none;
color: black;
display: block;
width: 100%;
height: 100%;
@include flexbox(){
justify-content: center;
align-items: center;
}
}
&.active{
>a{
color: $primaryColor;
}
border-bottom-color: $primaryColor;
}
}
}
.content{
position: relative;
}
}
</style>
说明 :上肌的content区域内部,我们引入了这两个组件,当这两个组件隐藏与显示的时候,我们就可以通过transition来实现animate.css的动画过渡效果了
使用路由的方式切换
上面的动态组件也可以通过路由来进行切换
import Vue from 'vue'
import Router from 'vue-router';
import index from '@/pages/index';
import movieList from '@/components/movieList';
import cinemalList from '@/components/cinemalList';
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'index',
component: index,
children: [{
path: "movieList",
name: "movieList",
component: movieList
},
{
path: "cinemalList",
name: "cinemalList",
component: cinemalList
}
]
}]
})
说明:上面的路由配置文件
<template>
<div class="index">
<header class="header">
猫眼电影
</header>
<ul class="topNav">
<router-link :to="{name:'movieList'}" active-class="active" tag="li"><a href="#">影片</a></router-link>
<router-link :to="{name:'cinemalList'}" active-class="active" tag="li"><a href="#">影院</a></router-link>
</ul>
<div class="content">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</div>
</template>
<script>
export default {
name:"index",
data(){
return{
pageType:0
}
}
}
</script>
<style lang="scss" scoped>
@import "../scss/common.scss";
.index{
position: absolute;
width: 100%;
height: 100%;
left: 0px;
top: 0px;
.header{
height: $headerHeight;
@include flexbox(){
justify-content: center;
align-items: center;
}
font-size: 18px;
background-color: $primaryColor;
color: white;
}
.topNav{
@include flexbox(){
justify-content: center;
align-items: center;
};
li{
width: 50%;
height: 40px;
border-bottom: 3px solid lightgray;
>a{
text-decoration: none;
color: black;
display: block;
width: 100%;
height: 100%;
@include flexbox(){
justify-content: center;
align-items: center;
}
}
&.active{
>a{
color: $primaryColor;
}
border-bottom-color: $primaryColor;
}
}
}
.content{
position: relative;
}
}
</style>
说明:上面是index.vue的文件代码,请注意看
<router-link>
的配置
Vue中使用JS动画库
::: tip
在一个动画的执行周期中,Vue提供了不同的钩子函数来让我们可以自定义自己的js动画,当然也可以使用第三方js动画。在纯粹使用js动画时,可以使用:css="false"来避免Vue的CSS监测。
:::
::: tip
在钩子函数enter(el,done)和leave(el,done)中的done方法必须进行回调,否则将被同步执行,过渡会立即完成。
:::
<transition
@before-enter="handelBeforeEnter"
@enter="handleEnter"
@after-enter="handleAfterEnter"
@before-leave="handleBeforeLeave"
@leave="handleLeave"
@after-leave="handleAfterLeave"
>
<p v-if="isShow">Hello, world</p>
</transition>
<button @click="isShow=!isShow">切换</button>
var vm = new Vue({
el: '#app',
data() {
return {
isShow: true
}
},
methods: {
handelBeforeEnter(el) {
el.style.color = 'red';
console.log('before enter');
},
handleEnter(el,done) {
setTimeout(() => {
el.style.color = 'green';
done();
console.log('enter');
}, 1500)
},
handleAfterEnter(el) {
console.log('after enter');
},
handleBeforeLeave(el) {
el.style.color = 'yellow';
console.log('before leave');
},
handleLeave(el,done) {
setTimeout(() => {
el.style.color = 'blue';
done();
console.log('leave');
}, 1000)
},
handleAfterLeave(el) {
console.log('after leave');
}
}
})
Vue中列表过渡
::: tip
前面讲到的过渡/动画,全部是一个元素的过渡/动画,或者多个元素中的一个进行过渡/动画,可以使用transition-group组件来结合v-for进行列表的过渡/动画
:::
.item {
display: inline-block;
margin-right: 10px;
}
.v-enter,.v-leave-to {
opacity: 0;
transform: translateY(30px)
}
.v-enter-active, .v-leave-active {
transition: all 0.5s;
}
<transition-group>
<div v-for="(item,index) in list" :key="item" class="item">{{item}}</div>
</transition-group>
<button @click="handleAddClick">添加</button>
var vm = new Vue({
el: '#app',
data() {
return {
isShow: true,
list: [1,2,3,4,5]
}
},
methods: {
handleAddClick() {
let maxItem = this.list[this.list.length-1];
this.list.push(maxItem+1);
}
},
})