主要是利用vue 路由 route.matched属性 matched文档说明
本节目标
2-1 route.matched
与给定路由地址匹配的标准化的路由记录数组。
当路由路径是 /system/menu时 会匹配到两条路由记录
每条记录里 有我们所需要的meta字段
route.meta.title会作为路由面包屑导航名称,如果没有title就不显示在面包屑导航
2-2 导入element的面包屑组件 ElBreadcrumb和 ElBreadcrumbItem
2-3 安装path-to-regexp(这里有坑 不明确)
path-to-regexp可以将动态路由路径/user/:id 转换成正则表达式。Path-to-RegExp
# 安装固定版本npm install path-to-regexp@6.2.0 --save# npm默认安装使用时# import { compile } from 'path-to-regexp'# 老报错compile函数是undefined 时好时坏
这里我们要用它解决 面包屑导航是动态路由的情况下,点击面包屑导航router.push跳转时 怎么把动态参数填充进去 拼接成正常路由 /user/:class/role/:id + {id: 2, class: 3} => /user/3/role/2 然后正确跳转
例如:动态路径是 /user/:class/role/:id 我们要将{id: 2, class: 3}填充为完整路径 然后才能正确跳转const { compile } = require('path-to-regexp')const toPath = compile('/user/:class/role/:id')const path = toPath({ id: 2, class: 3 })console.log('path:', path) // path: /user/3/role/2
2-4 创建Breadcrumb组件
src/components/Breadcrumb/index.vue
<template><el-breadcrumb class="app-breadcrumb breadcrumb-container" separator="/"><el-breadcrumb-itemv-for="(item, index) in levelList":key="item.path"><!-- 面包屑导航最后一个是不可点击的 因为最后一个正是当前所显示的路由 --><spanv-if="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></el-breadcrumb></template><script lang="ts">import { defineComponent, ref, watch, onBeforeMount } from 'vue'import { useRoute, useRouter, RouteLocationMatched, RouteLocationRaw } from 'vue-router'import { compile } from 'path-to-regexp'type PartialRouteLocationMatched = Partial<RouteLocationMatched>export default defineComponent({name: 'Breadcrumb',setup() {const route = useRoute() // 相当于this.$route对象const router = useRouter() // 相当于this.$router对象const levelList = ref<Array<PartialRouteLocationMatched>>([]) // 导航列表 存放matched里筛选的路由记录// 判断是不是Dashboard路由const isDashboard = (route?: PartialRouteLocationMatched) => {const name = route && route.nameif (!name) {return false}return (name as string).trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()}// 获取面包屑导航const getBreadcrumb = () => {// 对匹配的路由进行过滤 过滤掉没有title属性的路由,没有title就无法作为面包屑导航let matched = route.matched.filter(item => item.meta && item.meta.title) as PartialRouteLocationMatched[]// 获取第一个匹配路由记录const first = matched[0]// 我们要把dashboard作为首页 始终固定在面包屑导航第一个 Dashboard/System/Menu Management// 如果第一个匹配到的路由记录不是dashboard 我们自己就把它放在记录数组的第一项if (!isDashboard(first)) {matched = ([{path: '/dashboard',meta: {title: 'Dashboard'}}] as PartialRouteLocationMatched[]).concat(matched)}// route.meta.breadcrumb自定义属性 如果为false 匹配到时 将不会再面包屑导航显示该路由// {// path: 'menu',// meta: {// title: 'Menu Management',// breadcrumb: false // 不显示在面包屑导航 默认true// }// }levelList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)}onBeforeMount(() => {getBreadcrumb()})watch(() => route.path, () => {getBreadcrumb()})// 主要是针对 动态路由 /user/:id 进行动态参数填充// path-to-regexp 文档说明 https://www.npmjs.com/package/path-to-regexpconst pathCompile = (path: string) => {// 根据路径变编译成正则函数 并接收具体参数 比如根据正则/user/:id 帮你将:id替换成具体路径const toPath = compile(path) // 比如 path /user/:idconst params = route.params // { id: 10 }return toPath(params) // toPath({ id: 10 }) => /user/10 返回填充后的路径}// 点击面包屑导航可跳转const handleLink = (route: RouteLocationMatched) => {const { path, redirect } = route// 如果是重定向路由 就走重定向路径if (redirect) {router.push(redirect as RouteLocationRaw)return}router.push(pathCompile(path))}return {levelList,handleLink}}})</script><style lang="scss" scoped>.app-breadcrumb.el-breadcrumb {display: inline-block;/* float: left; */line-height: 50px;font-size: 14px;margin-left: 8px;}.no-redirect {color: #97a8be;cursor: text;}</style><style lang="scss">.breadcrumb-enter-active,.breadcrumb-leave-active {transition: all .5s;}.breadcrumb-enter,.breadcrumb-leave-active {opacity: 0;transform: translateX(20px);}.breadcrumb-leave-active {position: absolute;}.breadcrumb-move {transition: all .5s;}</style>
本节参考源码
https://gitee.com/brolly/vue3-element-admin/commit/45c652324fed0f105d02ae40d61614d158a2c2b8
