需求:
前一个页面离开时有双开门动画,后一个页面有缩放动画的效果。
不太理解双开门动画的小伙伴,可以参考ppt的门动画
版本迭代
第一次迭代
设计
第一想法就是通过创建一个父元素,并为其添加两个子元素,分别给这两个子元素设置vue动画来实现。
实现
//双开门动画组件 parent.vue
<template>
<transition name="door">
<div class="door">
<div class="door-left"></div>
<div class="door-right"></div>
</div>
</transition>
</template>
<style lang="less" scoped>
//vue动画实现
.door-enter-active,
.door-leave-active {
position: absolute;
top: 0;
left: 0;
transition: all 3s ease;
.door-left,
.door-right {
transition: all 3s ease;
}
}
.door-enter {
position: absolute;
top: 0;
left: 0;
.door-left {
transform: rotateY(-90deg);
}
.door-right {
transform: rotateY(90deg);
}
}
.door-leave {
position: absolute;
top: 0;
left: 0;
}
.door-leave-to {
.door-left {
transform: rotateY(-90deg);
}
.door-right {
transform: rotateY(90deg);
}
}
</style>
//APP.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/parent">parent</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/multi-element">Multielement</router-link> |
<router-link to="/list">list</router-link>
</div>
<transition :name="name">
<router-view ref="view" />
</transition>
</div>
</template>
<script>
export default {
data() {
return {
name: "parant",
};
},
watch: {
$route(to, from) {
//通过监听$route的to和from值,来设置name的取值
if (from.name === "parent") {
this.name = "parent";
} else {
this.name = "index";
}
}
}
};
<style lang="less">
.parent-enter-active {
animation: parent-in 3.5s;
position: absolute;
top: 0;
}
.parent-leave-active {
animation: parent-in 3.5s reverse;
}
@keyframes parent-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
</style>
上面给parent.vue - 也就是需要设置双开门动画的组件以及最外层的App.vue组件都设置了transition的css动画。
存在的问题
但是结果并不是很理想,因为App.vue设置的transition动画会覆盖掉parent.vue中设置的动画。
解决方案
经过思考,我们试着将App.vue中的transition去掉,用给router-view设置动态的class值来代替。而这就是我们第二次迭代所要修改的地方。
第二次迭代
//App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/parent">parent</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/multi-element">Multielement</router-link> |
<router-link to="/list">list</router-link>
</div>
<router-view :class="{ view: isView }" ref="view" />
</div>
</template>
<script>
export default {
data() {
return {
isView: false
};
},
watch: {
$route(to, from) {
if (from.name === "parent") {
this.isView = true;