likes
comments
collection
share

封装 ElementPlus 面包屑 Breadcrumb

作者站长头像
站长
· 阅读数 24

需求:

项目开发过程中每次路由跳转都需要修改面包屑,代码重复率很高。以下是针对 ElementPlus 面包屑 Breadcrumb 的封装,来达到降低重复率的目的。

想法解释:

既然每次点击侧边导航栏或者菜单 menu 使得路由变化,那么只要取到各层级路由的 name 就好。这里考虑 router 存在嵌套,即有 children。基于此,我们看一下路由前置守卫方法中的参数 to 的内容

router.beforeEach((to, from, next) => {
  console.log( '%c [to]: ', 'color: #bf2c9f; background: pink; font-size: 13px;', to);
 });

封装 ElementPlus 面包屑 Breadcrumb

这里我们关注 matched, 发现列表顺序中 name 确实是层级关系。

我们处理这个数组就可以得到面包屑的层级,如下图:

封装 ElementPlus 面包屑 Breadcrumb

具体实现:

组件路径:src\components\common\Crumbs.vue

通用型组件我们需要将 ElementPlus 关于面包屑的所有实现 都涵盖,再加入自己的需要。我们要添加的其实就是 crumbItemList ;

<template>
  <el-breadcrumb
    :separator="crumbProps.separator"
    :separator-icon="crumbProps.separatorIcon"
    style="padding: 0.5rem 0"
  >
    <el-breadcrumb-item
      v-for="item in crumbProps.crumbItemList"
      :key="item.name"
      :to="item.to"
      :replace="item.replace"
    >
      <slot>{{ item.name }}</slot>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>
<script lang="ts" setup>
interface CrumbProps {
  separator?: string;
  separatorIcon?: string;
  crumbItemList: {
    to: { path: string; [index: string]: any }; // 和路由的 to 很相似
    replace?: boolean;
    name: string;
  }[];
}
const crumbProps = defineProps<CrumbProps>();
</script>

如何使用:

路径:src\main.ts

由于每次路由跳转都更新面包屑,这里使用到状态管理 pinia ,在路由前置守卫中更改 crumbItemList 内容即可。

router.beforeEach((to, from, next) => {
  const crumbItemList = to.matched.map((item) => ({
    to: { ...item },
    name: item.name
  }));
  crumbStore.replaceCrumb(crumbItemList);
});

pinia 的使用:

路径:src\store\index.ts

考虑到存在页面下可能有不存在嵌套路由下的情况,进入下一页面需要增加面包屑,这里加入了action pushCrumb 方法,返回上一页面 sliceLastCrumb 方法

import { defineStore } from 'pinia';

export const useCrumbStore = defineStore({
  id: 'crumbs',
  state: () => ({
    crumbItemList: [
      {
        to: {
          path: '/'
        },
        name: '首页'
      }
    ]
  }),
  actions: {
    pushCrumb(crumbItem: any) {
      this.crumbItemList.push(crumbItem);
    },
    sliceLastCrumb() {
      this.crumbItemList.splice(-1);
    },
    replaceCrumb(crumbItemList: any[]) {
      this.crumbItemList = crumbItemList;
    }
  }
});

结语:

实际开发中,面包屑是与侧边导航栏一起使用的,涉及一个问题,每次页面刷新,menu 的 active 项需要突出显示,其实在 pinia 中增加一个 useMenuItemActiveStore 在路由前置守卫方法中 更改menuItem 的 active 即可。