vue嵌套路由制作面包屑
嵌套路由本身很简单,官方文档描述也都很仔细。
嵌套路由简单描述
一般情况下如下面的代码展示的一样,
/join
是父页面,在@/views/join/index.vue
这个vue
文件中,需要有一个<router-view />
去接收嵌套路由的子页面。也就是代码展示的@/views/join/detail.vue
这个vue
文件。这种情况一般就是父页面需要显示不同的组件,或者子页面需要用到的方法。很常见的功能比如是有几个导航,切换加载页面。
export default {
path: '/join', // 加入我们
meta: {
breadName: 'Join'
},
name: 'Join',
component: () => import( /* webpackChunkName: "Join" */ '@/views/join/index.vue'),
children: [
{
// 加入我们详情
path: 'detail/:id',
name: 'JoinDetail',
meta: {
breadName: 'JoinDetail'
},
component: () => import(/* webpackChunkName: "JoinDetail" */ '@/views/join/detail.vue'),
}
]
}
上面代码实现的例子
嵌套路由和面包屑的关系
在
vue
中,我们不可能自己去写一个数组去记录页面的跳转路径,用户浏览的页面轨迹。因为通常这些都已经在vue-router
中已经能拿到。如下代码所展示的,通过this.$route.matched
可以拿到当前页面的路径信息。用上面的代码举例,当页面在/join/detail/123
的路径底下的时候,这时候matched
可以拿到/join
和/join/detail/123
let matched = this.$route.matched;
matched = matched.filter(item => {
return item && item.meta && item.meta.breadName;
});
const temp = matched.map((item) => {
return {
path: item.path,
title: item.meta.breadName,
}
});
const result = [{
path: '/',
title: 'Home',
}].concat(temp)
matched的源数据如下图展示的这样,我们通过
matched
可以拿到/join
和/join/detail/123
,一般面包屑会在带上一个首页,所以都要自己手动拼一个首页的内容。拿到这个数组,我们就可以通过循环,自己写出面包屑,相信作为前端应该都会。
嵌套路由刷新页面丢失问题
按照上面两个步骤,基本上是可以实现面包屑的功能,但是会出现当用户在
官方文档解释/join/detail/123
的路径下的时候,强制刷新页面,页面就丢失了。官方文档是这样解释的。
大概的意思,当有嵌套路由,并且子页面是和父页面一点关系都没有的时候。我们在根节点上需要有一个
router-view
去接收它。仔细观察下下面的代码和上面的代码,两个路由有什么不同的地方?在主路由上,我们用了一个layou
t组件接收了它。在children
底下,有一个任何path
的都可以访问匹配到的页面。
export default {
path: '/join', // 加入我们
meta: {
breadName: 'Join'
},
component: ()=> import(/* webpackChunkName: "Layout" */ '@/components/layout.vue'),
children: [
{
path:'',
name: 'Join',
component: () => import( /* webpackChunkName: "Join" */ '@/views/join/index.vue'),
},
{
// 加入我们详情
path: 'detail/:id',
name: 'JoinDetail',
meta: {
breadName: 'JoinDetail'
},
component: () => import(/* webpackChunkName: "JoinDetail" */ '@/views/join/detail.vue'),
}
]
}
layout.vue
做的事情其实很简单,它只是有一个router-view
去接页面,至于具体展示什么,由children
去决定。这样就不会导致强制刷新页面失败。
<template>
<div>
<router-view :key="key"/>
</div>
</template>
<script>
export default {
name: 'r-layout',
computed: {
key() {
return this.$route.path + parseInt((Math.random() * 1000));
}
}
}
</script>
总结
如果父路由和子路由是有关联的,比如我们看淘宝的某个商品,可以通过
bar
来切换商品参数,商品介绍什之类的,可以采用第一个,最上面的方案。
如果父路由和子路由是没有任何关系,比如商品列表页面和商品详情页面。要采用第三种方案,需要有一个layout
去接收它。否则会出现刷新页面,页面丢失的情况。
面包屑则通过路由的match
,可以拿到当前页面的路由信息。通常情况下我们会在加上一个首页的路由。