概述
再微信当中,点击朋友圈,然后点击返回,会有一个友好的路由过度效果,看起来还是很舒适的,除开微信,其实很多移动端的app应用都有这个功能,现在记录一下vue项目中h5实现类似的效果。
实际项目效果图
项目体验地址:develop.kingchannels.cn:50609/h5
准备工作
要做这个动画效果,你需要对vue的内置transition组件有使用经验,如果没用过的话,建议自己根据官网的示例自己去试试。
实现
1.首先你需要准备多个路由页面,这里演示使用,只新建两个页面,一个充当首页(home),一个充当详情(detai)。
./pages/Detail.vue
<template>
<div class="page detail">
<p>详情页面</p>
<button @click="$router.back()">返回home页面</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
components: {},
};
</script>
<style lang="less">
.detail {
background-color: #008c8c;
}
</style>
./pages/Home.vue
<template>
<div class="page home">
<p>首页</p>
<button @click="$router.push('/detail')">到detial页面</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
components: {},
};
</script>
<style lang="less">
.home {
background-color: pink;
}
</style>
./router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import store from "../store/index";
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{
path: "/",
redirect: "/home",
},
{
path: "/home",
component: () => import("../pages/Home.vue"),
meta: {
index: 1,
},
},
{
path: "/detail",
component: () => import("../pages/Detail.vue"),
meta: {
index: 2,
},
},
],
});
// 设置路由切换动画,通过meta中定义层级关系
Vue.prototype.setoRouteTransitionName = function (to, from) {
let transitionName = "";
if (to.meta.index > from.meta.index) {
transitionName = "slide-l"; // 向左滑动
} else if (to.meta.index < from.meta.index) {
// 由次级到主级
transitionName = "slide-r";
} else {
transitionName = ""; // 同级无过渡效果
}
store.commit("setTransitionName", transitionName);
};
router.beforeEach((to, from, next) => {
Vue.prototype.setoRouteTransitionName(to, from);
next();
});
export default router;
./store/index.js 通过状态管理动态设置transitionname
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
//动态控制动画name属性
transitionName: "slide-l",
},
mutations: {
setTransitionName(state, data) {
state.transitionName = data;
},
},
});
./App.vue
<template>
<div class="app">
<!-- <transition :name="transitionName">
<router-view></router-view>
</transition> -->
<transition name="slide-l">
<router-view></router-view>
</transition>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
...mapState(["transitionName"]),
},
};
</script>
<style lang="less">
html,
#app,
body,
.page,
.app {
height: 100%;
width: 100%;
color: #fff;
}
.page {
text-align: center;
button {
color: #fff;
background-color: green;
width: 200px;
height: 50px;
margin-top: 300px;
}
}
//定义过度动画
.slide-l-enter-active,
.slide-l-leave-active,
.slide-r-enter-active,
.slide-r-leave-active {
transition: all 0.6s;
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
//左滑过度
.slide-l-enter {
opacity: 0;
transform: translateX(100%);
}
.slide-l-enter-to,
.slide-l-leave {
opacity: 1;
transform: translateX(0);
}
.slide-l-leave-to {
opacity: 0;
transform: translateX(-100%);
}
//右滑过度
.slide-r-enter {
opacity: 0;
transform: translateX(-100%);
}
.slide-r-enter-to,
.slide-r-leave {
opacity: 1;
transform: translateX(0);
}
.slide-r-leave-to {
opacity: 0;
transform: translateX(100%);
}
</style>