为实现APP内嵌H5开发页面与原生页面实现同样的跳转效果,我们利用Vue 提供了 <transition>
组件在单页面应用下来模拟原生的页面跳转。
因为项目需要用<keep-alive>
包裹缓存不活动的组件实例,所以原有App.vue
中代码是这样的:
<template>
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />
</div>
</template>
这里我们需要使用<transition-group>
标签进行包裹,并且为它的子元素设置上key
值:
<template>
<div id="app">
<transition-group :name="transitionName">
<div key="keepAlive" v-show="$route.meta.keepAlive">
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
</div>
<router-view v-if="!$route.meta.keepAlive" :key="$route.name" />
</transition-group>
</div>
</template>
然后,我们为<transition>
标签设置动态的name
,通过监听route
的变化,判断页面的前进或后退从而动态设置name
的值,来改变页面的滑入滑出效果,这里我们需要提前在路由中定义每个页面的路由深度,以便在route
变化时进行页面前进或后退的判断,路由深度定义:
const routes = [
{
path: "/reservationList",
name: "reservationList",
meta: {
keepAlive: true,
depth: 1
},
component: () => import("../views/reservation/reservationList.vue"),
},
{
path: "/reservationDel",
name: "reservationDel",
meta: {
depth: 2
},
component: () => import("../views/reservation/reservationDel.vue"),
}, ,
{
path: '/health-told',
name: 'health-told',
meta: {
depth: 3
},
component: () => import('../views/reservation/HealthTold.vue'),
},
{
path: '/health-info',
name: 'health-info',
meta: {
depth: 3
},
component: () => import('../views/reservation/HealthInfo.vue'),
}
]
这里我们通过route
中mate
的depth
属性来定义页面的深度,当然也可以通过路由的嵌套来定义。
然后在App.vue
的watch
中监听$route
的变化,为标签设置动态的name
值。这里需要注意的一点是有的页面是由原生页面直接跳转,来源路由的不包含depth
属性,所以我们需要设置默认depth
值,当页面由原生页面跳转过来时我们将name
属性置空,以免和原生跳转效果重叠。
export default {
data() {
return {
transitionName: '',
}
},
watch: {
$route(to, from) {
let toDepth = to.meta.depth || 0,
fromDepth = from.meta.depth || 0
if (fromDepth === 0) this.transitionName = ''
else if (toDepth > fromDepth) this.transitionName = 'slide-left'
else this.transitionName = 'slide-right'
},
},
}
</script>
最后,为页面的滑入滑出定义样式:
.slide-right-enter-active,
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active {
will-change: transform;
transition: all 500ms;
}
.slide-right-enter {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
.slide-right-leave-active {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
.slide-left-enter {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
.slide-left-leave-active {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
最终实现效果: