现在我们开始学习一些vue-router的高级一点的内容,这节课我们一起学习如何在页面跳转时添加一些过渡动效。
我们还是继续在vue-router4快速入门的例子的基础上改,先把之前的嵌套路由的代码去掉,就剩下一个简单的首页、列表页和用户详情页。
添加过渡效果需要用到vue自带的内置组件transition,transition组件的作用就是在它的里面的内容发生变化时,增加过渡效果,具体用法在这里。
给页面跳转增加过渡效果的方式跟之前的版本区别比较大,这里要在router-view上使用v-slot获取对应的组件,使用component动态组件来渲染这个组件,然后用transition包裹住这个动态组件:
<router-view v-slot="{ Component }">
<transition name="fade">
<component :is="Component" />
</transition>
</router-view>
这样在页面切换时,动态组件的内容发生了变化,这里我们定义了一个名字是fade的transition,就会有一个fade的过渡效果了,不过我们需要用css定义这个fade效果:
.fade-enter-active {
transition: opacity 0.5s ease;
}
.fade-leave-active {
transition: none;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
transition大概就是这样一个用法,这里定义的过渡时,如果组件离开页面,就直接消失,如果组件进入页面就有个0.5秒的透明度动画。
这么写好以后,点击跳转页面,发现并没有效果。原来,使用transition时,页面的vue文件的template下必须只有一个根元素。
比如index.vue应该是:
<template>
<div class="page">
<div>这里是首页</div>
<router-link to="/list">点击跳转到列表页</router-link>
</div>
</template>
只有一个根div,这样改完之后就有淡入的fade效果了。
为了效果更好一点,让每个页面都全屏大小,定位在顶部。
添加一个class,叫page
.page {
position: absolute;
width: 100%;
height: 100vh;
left: 0;
top: 0;
}
每个页面的根元素上都加上这个class,淡入的效果就完成了。
淡入的效果还是不太好看,下面按照官网的例子,做一个进入下层页面从右边滑过来、进入上层页面从左边滑过来的例子,
这时候,transition的效果是动态的,一共两个,slide-left和slide-right,我们在route配置时候的meta里增加一个属性,表示transition的效果,默认是slide-left
router.js
{
path: '/index',
component: () => import('./views/index'),
name: 'index',
meta: {
title: '首页',
keepAlive: true,
transition: 'slide-left', // 增加
},
},
然后在App.vue里面,动态设置transition的name属性:
<router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition"> // name是动态绑定的
<component :is="Component" />
</transition>
</router-view>
在router.js中增加导航守卫,动态的更改route里面meta的transition的值:
router.afterEach((to, from) => {
// 新增
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
})
这样过渡的效果就是动态的了,在slide-left和slide-right之间变化,
最后在加上效果的css代码:
.slide-left-enter-active {
transition: transform 0.5s ease;
}
.slide-left-leave-active {
transition: none;
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translate3d(100vw, 0, 0);
}
.slide-right-enter-active {
transition: transform 0.5s ease;
}
.slide-right-leave-active {
transition: none;
}
.slide-right-enter-from,
.slide-right-leave-to {
transform: translate3d(-100vw, 0, 0);
}
这就完成了,
最后效果就是进入用户详情页,页面时从右边滑过来,从用户详情页返回,页面是从左边滑过来。
下面把整个项目的代码贴出来
App.vue
<template>
<div>
<router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition">
<component :is="Component" />
</transition>
</router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
.slide-left-enter-active {
transition: transform 0.5s ease;
}
.slide-left-leave-active {
transition: none;
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translate3d(100vw, 0, 0);
}
.slide-right-enter-active {
transition: transform 0.5s ease;
}
.slide-right-leave-active {
transition: none;
}
.slide-right-enter-from,
.slide-right-leave-to {
transform: translate3d(-100vw, 0, 0);
}
.page {
position: absolute;
width: 100%;
height: 100vh;
left: 0;
top: 0;
}
</style>
router.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/index',
component: () => import('./views/index'),
name: 'index',
meta: {
title: '首页',
keepAlive: true,
transition: 'slide-left', // 新增
},
},
{
path: '/list',
component: () => import('./views/list'),
name: 'list',
meta: {
title: '用户列表',
keepAlive: true,
transition: 'slide-left', // 新增
},
},
{
path: '/userDetail/:id',
component: () => import('./views/userDetail'),
name: 'userDetail',
meta: {
title: '用户详情',
keepAlive: true,
transition: 'slide-left', // 新增
},
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
router.afterEach((to, from) => {
// 新增
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
})
export default router
index.vue
<template>
<div class="page">
<div>这里是首页</div>
<router-link to="/list">点击跳转到列表页</router-link>
</div>
</template>
<script>
export default {}
</script>
<style></style>
list.vue
<template>
<div class="page">
<div>这里是列表页</div>
<router-link to="/index">点击跳转到首页</router-link>
<ul>
<li v-for="item in userList" :key="item.id">
<router-link
:to="{
name: 'userDetail',
params: {
id: item.id,
},
query: {
name: item.name,
},
}"
>点击查看{{ item.name }}</router-link
>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
userList: [
{
name: '亚历山大',
id: '01',
},
{
name: '凯撒',
id: '02',
},
{
name: '屋大维',
id: '03',
},
],
}
},
}
</script>
<style></style>
userDetail.vue
<template>
<div class="page">用户详情页获取到了id:{{ id }},他的名字是:{{ name }}</div>
</template>
<script>
export default {
data() {
return {
id: '',
name: '',
}
},
mounted() {
this.id = this.$route.params.id
this.name = this.$route.query.name
},
}
</script>
<style></style>