主要是利用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-item
v-for="(item, index) in levelList"
:key="item.path"
>
<!-- 面包屑导航最后一个是不可点击的 因为最后一个正是当前所显示的路由 -->
<span
v-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.name
if (!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-regexp
const pathCompile = (path: string) => {
// 根据路径变编译成正则函数 并接收具体参数 比如根据正则/user/:id 帮你将:id替换成具体路径
const toPath = compile(path) // 比如 path /user/:id
const 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