vue嵌套路由制作面包屑

2021-03-04  本文已影响0人  RadishHuang

嵌套路由本身很简单,官方文档描述也都很仔细。

官方文档入口

嵌套路由简单描述

一般情况下如下面的代码展示的一样,/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可以拿到/join/join/detail/123,一般面包屑会在带上一个首页,所以都要自己手动拼一个首页的内容。拿到这个数组,我们就可以通过循环,自己写出面包屑,相信作为前端应该都会。

matched的源数据

嵌套路由刷新页面丢失问题

按照上面两个步骤,基本上是可以实现面包屑的功能,但是会出现当用户在/join/detail/123的路径下的时候,强制刷新页面,页面就丢失了。官方文档是这样解释的。

官方文档解释

大概的意思,当有嵌套路由,并且子页面是和父页面一点关系都没有的时候。我们在根节点上需要有一个router-view去接收它。仔细观察下下面的代码和上面的代码,两个路由有什么不同的地方?在主路由上,我们用了一个layout组件接收了它。在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,可以拿到当前页面的路由信息。通常情况下我们会在加上一个首页的路由。

上一篇下一篇

猜你喜欢

热点阅读