目录

实现效果

router/index.js

Layout.vue

LayoutBlank.vue


面包屑组件可以清晰的显示当前页面的路径,快速返回之前的任意页面。

那么三级或者多级路由应该怎样配置,这里以自己写的代码为例,先看看实现效果

实现效果

 这里是三级路由的配置,面包屑展示的路径是在router里面配置的。

看起来是“三级”,其实是多级嵌套起来的,

借助了两个layout才展示出“三级”甚至“四级”的路由,如图:

 

面包屑上黑色的路径是能点击跳转的。

首先是路由的配置如下

router/index.js

export const asyncRoutes = [
  //后台管理系统
  {
    path: '/background',
    component: Layout,//第一个layout,带main
    name: 'background-manage',
    meta: {
      title: '后台管理',
      icon: 'fa fa-tasks'
    },
    redirect: 'noRedirect',
    children: [
      //后台管理系统--用户管理————“二级路由”
      {
        path: 'backgroundUser',
        name: 'backgroundUser-manage',
        component: LayoutBlank,
        meta: {
          title: '用户管理',
          icon: 'fa fa-users'
        },
        //这里写用户管理里面的子页面
        children: [
          //第一个是用户管理的页面
          {
            path: '',
            name: 'backgroundUser',//如果页面代码里面跳转路由是通过name,那么name一定要唯一
            component: () => import('@/views/background/backgroundUser.vue'),
            hidden: true//这个一定要写,要不然左侧导航栏里面就会出现很多级
          },
          //用户管理的子页面,比如新增用户之类的页面
          {
            path: 'backgroundUserCreate/:id',
            name: 'backgroundUser',
            component: () => import('@/views/background/backgroundUserCreate.vue'),
            meta: {
              title: '新建用户',
              icon: 'fa fa-users',
            },
            props: true,
            hidden: true
          }
        ]
      },
      //后台管理系统--项目管理————“三级路由”或者更多
      {
        path: 'project',
        component: LayoutBlank,//第二个layout 不带main,下文解释
        meta: {
          title: '项目管理',
          icon: 'fa fa-list'
        },
        children: [
          //第一个页面时项目管理的页面,和上面的用户管理一样
          {
            path: '',
            name: 'project',
            component: () => import('@/views/background/project.vue'),
            hidden: true
          },
          {
            path: 'projectManage',
            component: LayoutBlank,//一定是这个
            meta: { title: '管理项目成员', icon: 'fa fa-users'}
            props: true,
            hidden: true,
            children: [
              //这里是“管理项目成员”的页面
              {
                path: '',
                name: 'project-manage',
                component: () => import('@/views/background/projectUpdate.vue'),
                hidden: true,
                props: true
              },
              //管理项目成员的子页面——成员详情
              {
                path: 'projectMemberInfo',
                name: 'projectMember-info',
                component: () => import('@/views/background/projectMemberInfo.vue'),
                meta: { title: '成员详情', icon: 'fa fa-users'},
                hidden: true
              }
            ]
          }
        ]
      },
      // 日志管理
      {
        path: 'project-op-log',
        component: LayoutBlank,
        meta: {
          title: '日志管理',
          icon: 'fa fa-file-medical-alt'
        },
        children: [
          {
            path: '',
            name: 'projectOpLog',
            component: () => import('@/views/background/userOpLogs.vue'),
            hidden: true
          }
        ]
      }
    ]
  },
  //个人设置
  {
    path: '/personalSetting',
    component: Layout,
    children: [
      {
        path: 'userSetting',
        component: () => import('@/views/user/index.vue'),
        name: 'userSetting',
        accessControl: true,
        meta: { title: '个人设置', icon: 'fa fa-user-circle' }
      }
    ]
  },
  // 404 page must be placed at the end !!!
  // using pathMatch install of "*" in vue-router 4.0
  { path: '/:pathMatch(.*)', redirect: '/404', hidden: true }
]

两个layout页面,主layout的HTML是这样的:

Layout.vue

<template>
  <div :class="classObj" class="layout-wrapper">
    <!--left side-->
    <Sidebar  class="sidebar-container" />
    <!--right container-->
    <div class="main-container">
      <Navbar  />
      <TagsView  />
      <AppMain />
    </div>
  </div>
</template>

第二个layout是空白的只是为了占位:

LayoutBlank.vue

<template>
  <div class="layout-wrapper">
    <!--right container-->
    <div>
      <router-view />
    </div>
  </div>
</template>
<!--原理vue2.0-->
<script>
/*可以设置默认的名字*/
export default {
  name: 'LayoutBlank'
}
</script>

以上两个layout在路由里面使用时需要先import

除了以上,引用面包屑还需要配置路由的引用方式,在layout文件夹下面的components文件夹里面新建一个文件 Breadcrumb.vue,在这里引用面包屑组件,具体的代码可以参考这里:

<template>
  <el-breadcrumb class="app-breadcrumb" separator="/">
    <!--has transition  Judging by settings.mainNeedAnimation-->
    <transition-group v-if="settings.mainNeedAnimation" name="breadcrumb">
      <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
        <span v-if="item.redirect === 'noRedirect' || index === levelList.length - 1" class="no-redirect">
          {{ item.meta?.title }}
        </span>
        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
      </el-breadcrumb-item>
    </transition-group>
    <!--no transition-->
    <template v-else>
      <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
        <span v-if="item.redirect === 'noRedirect' || index === levelList.length - 1" class="no-redirect">
          {{ item.meta?.title }}
        </span>
        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
      </el-breadcrumb-item>
    </template>
  </el-breadcrumb>
</template>

<script setup>
import { compile } from 'path-to-regexp'
import setting from '@/settings'
const levelList = ref(null)

//Whether close the animation fo breadcrumb

import { useAppStore } from '@/store/app'
const appStore = useAppStore()
const settings = computed(() => {
  return appStore.settings
})

const route = useRoute()
const getBreadcrumb = () => {
  // only show routes with meta.title
  let matched = route.matched.filter((item) => item.meta && item.meta.title)
  const first = matched[0]
  if (!isDashboard(first)) {
    //it can replace the first page if not exits
    matched = [{ path: '/', meta: { title: setting.title } }].concat(matched)
  }
  levelList.value = matched.filter((item) => item.meta && item.meta.title && item.meta.breadcrumb !== false)
}

const isDashboard = (route) => {
  const name = route?.name
  if (!name) {
    return false
  }
  return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
}
const pathCompile = (path) => {
  const { params } = route
  const toPath = compile(path)
  return toPath(params)
}
const router = useRouter()
const handleLink = (item) => {
  const { redirect, path } = item
  if (redirect) {
    router.push(redirect)
    return
  }
  if (path) {
    router.push(pathCompile(path))
  }
}
watch(
  () => route.path,
  () => {
    getBreadcrumb()
  },
  { immediate: true }
)
onBeforeMount(() => {
  getBreadcrumb()
})
</script>

<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  font-size: 14px;
  line-height: 50px;
  margin-left: 8px;

  .no-redirect {
    color: #97a8be;
    cursor: text;
  }
}
</style>

这个文件里的主要时读取路由表的路径,可以参考这部分的代码试着写一个三级或者多级路由,v-if="settings.mainNeedAnimation"是项目的配置,可以忽略这部分。

Logo

前往低代码交流专区

更多推荐