vue3+elemenuPlus 面包屑

4,835 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

路由文件

面包屑是基于路由的。这里我们要说一下meta(元数据)

meta

自定义元数据,也就是一些我们自己要使用的一些数据。如下那我们在meta中添加了 title和icon属性,分别用于我们面包屑的文字和 导航栏的图标。

 meta: { title:'用户管理',icon: 'User' },

路由文件

import ManageLayout from '@/layout/ManageLayout.vue'
import { RouterView } from 'vue-router'
const manageRouter =  // 管理端
{
  path:'/manage/',
  component : ManageLayout,
  children:[
    {
      path:'',
      name:'home',
      component:()=>import('@/manage/Home/Home.vue'),
      meta: { title: '首页', icon: 'HomeFilled' },
    },
    {
      path:'/user',
      name:'user',
      component:RouterView,
      meta: { title:'用户管理',icon: 'User' },
      children:[
        {
          path:'blacklist',
          name:'blacklist',
          component:()=>import('@/manage/UserManage/BlackList/BlackList.vue'),
          meta: { title:'黑名单管理'},
        }
      ]  
    },
    { 
        path:'/dashboard',
        name:'dashboard',
        component:RouterView,
        meta: { title:'数据看板',icon: 'TrendCharts'},
        children:[
          {
            path:'pv',
            name:'pv',
            component:()=>import('@/manage/DashBoard/PV/PV.vue'),
            meta: { title:'浏览量'},
            
          }
        ]  
      
    }
  ]
}
export default manageRouter

注意一下我这里是在另一个路由文件中引入的上面路由,正常的路由配置是:数组中包着对象。

const routes: RouteRecordRaw[] = [
  // 是空时代理到client
  {
    path: '',
    redirect:'/client'
  },
  // 管理端
  manageRouter,
  // 客户端
  clientRouter,
 
];

elementPlus 中面包屑

如下官方文档中,有两种面包屑。一个是基础的,一个是添加图标分割的。

image.png

基础面包屑

传入separator="/"配置项,面包屑就会按照/进行分隔。

<template>
  <el-breadcrumb separator="/">
    <el-breadcrumb-item :to="{ path: '/' }">homepage</el-breadcrumb-item>
    <el-breadcrumb-item
      ><a href="/">promotion management</a></el-breadcrumb-item
    >
    <el-breadcrumb-item>promotion list</el-breadcrumb-item>
    <el-breadcrumb-item>promotion detail</el-breadcrumb-item>
  </el-breadcrumb>
</template>

图标面包屑

separator="/"配置项换为 :separator-icon 配置项。然后将图标组件传入,这里是动态的所以需要:

<template>
  <el-breadcrumb :separator-icon="ArrowRight">
    <el-breadcrumb-item :to="{ path: '/' }">homepage</el-breadcrumb-item>
    <el-breadcrumb-item>promotion management</el-breadcrumb-item>
    <el-breadcrumb-item>promotion list</el-breadcrumb-item>
    <el-breadcrumb-item>promotion detail</el-breadcrumb-item>
  </el-breadcrumb>
</template>

<script lang="ts" setup>
import { ArrowRight } from '@element-plus/icons-vue'
</script>

开始我们的面包屑

封装成组件

Breadcrumb.vue

把elementplus的代码复制过来。然后在我们导航栏文件中引入这个组件。

<template>
  <el-breadcrumb :separator-icon="ArrowRight" class="bread">
    <el-breadcrumb-item :to="{ path: '/' }">homepage</el-breadcrumb-item>
    <el-breadcrumb-item>promotion management</el-breadcrumb-item>
    <el-breadcrumb-item>promotion list</el-breadcrumb-item>
    <el-breadcrumb-item>promotion detail</el-breadcrumb-item>
  </el-breadcrumb>
</template>

<script lang="ts" setup>
import { ArrowRight } from '@element-plus/icons-vue'
</script>

<style>
/* 这里为了跟收起图标对其 */
.bread{
    margin-top:8px;
}
</style>

导航栏文件中引入组件

image.png

先看一下效果。 image.png

获得当前所在路由

需要使用useRouter() Hook来获取。此时的这个router是经过ref()处理过的响应式数据。所以获取他的值需要.value.match是当前路由的匹配记录。

<template>
  <el-breadcrumb :separator-icon="ArrowRight" class="bread">
    <el-breadcrumb-item :to="{ path: '/' }">homepage</el-breadcrumb-item>
    <el-breadcrumb-item>promotion management</el-breadcrumb-item>
    <el-breadcrumb-item>promotion list</el-breadcrumb-item>
    <el-breadcrumb-item>promotion detail</el-breadcrumb-item>
  </el-breadcrumb>
</template>

<script lang="ts" setup>
import { useRouter } from "vue-router";
import { ArrowRight } from '@element-plus/icons-vue'
const router = useRouter()
// 当前路由的匹配记录
console.log(router.currentRoute.value.matched)
</script>

<style>
/* 这里为了跟收起图标对其 */
.bread{
    margin-top:8px;
}
</style>

我们看一下打印的结果

  • 索引为0的,是我们为了区分客户端和管理端包着的一层路由,并不要展示在面包屑中
  • 索引为1的,是一级导航栏的路由
  • 索引为2的,是二级导航栏的路由
  • 我们刚才添加的meta属性也都在其中了 image.png image.png

渲染动态面包屑

过滤

  • 首先,将没有用的那一层,也就是索引为0的那一项过滤掉。因为其没有meta.title,所以通过meta.title将其过滤掉
  • 这里也用到了computed计算,需要引入一下
<script lang="ts" setup>
import { useRouter } from "vue-router";
import { ArrowRight } from '@element-plus/icons-vue'
import { computed } from "vue";
const router = useRouter()
// 当前路由的匹配记录
console.log(router.currentRoute.value.matched)
const routers = computed(()=>{
    // 过滤掉没有meta的 
    return router.currentRoute.value.matched.filter(item=>item.meta.title)
})
</script>

遍历

  • v-for 遍历routers
  • key 遍历后需要一个唯一key
  • to 是点击面包屑跳转的路由
  • 展示的值是 meta中的title
<template>
  <el-breadcrumb :separator-icon="ArrowRight" class="bread">
    <el-breadcrumb-item v-for="item in routers" :key="item.path" :to="{ path: item?.path }">
            {{item?.meta?.title}}
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>

最终效果 image.png

vueRouter

中文官网 ✈️

我们看一下,路由元数据的TypeScript。就是进行了一下数据类型的约束

image.png

定义文件

主要这个文件所在层级哦!

image.png

在src文件下,新建一个 router.d.ts (这个文件名可以随便起)。但是最好规范成xx.d。 📢最后的.ts文件后缀格式 可一定得是 .ts

router.d.ts

通过扩展 RouteMeta来修改meta的数据类型约束。我们添加了title和icon都是字符串类型。

// typings.d.ts or router.ts
import 'vue-router'

declare module 'vue-router' {
  interface RouteMeta {
   title:string,
   icon:string
  }
}

回到面包屑组件

这是meta.之后,会给我们提示 title image.png 并且鼠标悬停在上面也会有相应的提示

image.png