动态面包屑

165 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

前言

面包屑效果如下

4.png

以上效果可以使用两种方法实现

  1. 静态面包屑
  2. 动态面包屑

静态面包屑指在每个页面中写死对应值,如此的话每个页面都需要写一遍,如果新增页面,还需要手动更改面包屑的值,过程繁琐且不好维护

使用动态面包屑,就可以根据当前路由的变化动态生成当前的面包屑,再也不需要手动添加。

实现

基本结构

首先先写固定的值实现面包屑的基本样式

components/Breadcrumb/index

<template>
  <el-breadcrumb class="breadcrumb" separator="/">
    <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
    <!-- 面包屑的最后一项 -->
    <el-breadcrumb-item>
      <span class="no-redirect">人员列表</span>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>

数据处理

要实现动态渲染,需要获取动态数据,我们可以用数组保存动态数据,动态面包屑的每一项为数组的一个值

components/Breadcrumb/index

<script setup>
import { ref } from 'vue'
// 面包屑数据
const breadcrumbData = ref([])
</script>

我们希望根据路由的变化,生成不同的面包屑数据,所以可以监听路由的变化,之后去获取路由变化后的面包屑数据,getBreadcrumbData为获取面包屑数据的方法

components/Breadcrumb/index


<script setup>
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
// 监听路由变化时触发
watch(
  route,
  () => {
    getBreadcrumbData()
  },
  {
    immediate: true
  }
)
</script>

接下来去完成getBreadcrumbData方法的处理

处理数据时需要用的route.matched()

5.png

route.matched

1: 一个数组,包含当前路由的所有嵌套路径片段的路由记录

2: 一个路由匹配到的所有路由记录会暴露为 route 对象 (还有在导航守卫中的路由对象) 的 route.matched 数组

如当前地址为http://localhost:8080/#/user/role

在控制台打印route.matched

3.png

就可以拿到每一项的路由元信息,其中保存有title

接下来处理getBreadcrumbData方法

const getBreadcrumbData = () => {
  // 筛选出存在title的路由
  breadcrumbData.value = route.matched.filter(
    (item) => item.meta && item.meta.title
  )
}

渲染

遍历breadcrumbData渲染,注意数组最后一项有不同的样式,用v-if判断是否是最后一项,使用不同的类名渲染不同的样式,每一项的值为路由元信息中的title

<template>
  <el-breadcrumb separator="/" class="breadcrumb">
    // 动画
    <transition-group name="breadcrumb">
      <el-breadcrumb-item
        v-for="(item, index) in breadcrumbData"
        :key="item.path"
      >
        <!-- 不可点击 -->
        <span class="no-redirect" v-if="index === breadcrumbData.length - 1">{{
          generateTitle(item.meta.title)
        }}</span>
        <!-- 可点击 -->
        <span class="redirect" v-else @click="onLinkClick(item)">{{
          generateTitle(item.meta.title)
        }}</span>
      </el-breadcrumb-item>
    </transition-group>
  </el-breadcrumb>
</template>

补充一下generateTitle方法为处理国际化

import i18n from '@/i18n'

export function generateTitle(title) {
  return i18n.global.t('msg.route.' + title)
}