Vue3-面包屑Breadcrumb开发

举报
林太白 发表于 2025/03/04 13:29:18 2025/03/04
63 0 0
【摘要】 Vue3-面包屑Breadcrumb开发

❤ Vue3-面包屑Breadcrumb开发

1. 面包屑组件Breadcrumb

在后台管理之中,面包屑是一个非常重要的组件,它可以帮助用户快速定位当前页面在系统中的位置,并且可以方便地返回到上一级页面。

接下来我们就开发一个面包屑组件Breadcrumb,这里我们使用Element Plus库中的Breadcrumb组件来实现。

2、面包屑组件开发

首先,我们需要在components文件夹下创建一个Breadcrumb.vue文件,并在其中编写面包屑组件的代码。

👉 先看看官方给我们提供的案例

<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>

👉分割部分设置为iconfont的图标

只需要更改separator-icon 属性即可,这个属性负责控制面包屑的分隔符,设置为ArrowRight,就可以使用Element Plus库中的ArrowRight图标作为分隔符。

<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>

简单预览一下

3、渲染面包屑

接下来,我们引入面包屑组件,并在其中渲染面包屑。

简单的去匹配一下我们的路由表,然后渲染出来即可,代码如下:

这里需要注意的就是meta中的title字段,用来表示面包屑的名称,如果没有这个字段,那么这个路由就不会被渲染到面包屑中

<template>
  <el-breadcrumb separator="/">
    <el-breadcrumb-item v-for="(val,index) in breadcrumbList" :key="val+''+index">
      <a href="/admin" v-if="val.path=='/'">首页</a>
      <!-- <a v-else-if="val.path=='/admin'"></a> -->
      <a :href="val.path" v-else>{{val.meta?.title}}</a>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>
<script setup>
import {getCurrentInstance,ref,onMounted} from 'vue'
const { proxy } = getCurrentInstance()// 获取当前实例
const route=proxy.$useRoute();
const breadcrumbList=ref([]);
onMounted(()=>{
  breadcrumbList.value=route.matched;
})
</script>

接下来就可以顺利使用了,当然了,接下来继续去完善和优化面包屑部分

4、优化

👉 动态匹配路径

点击不同的路径以后我们发现,面包屑的路径还是之前的,来回切换的过程之中根本无法做到路径与组件一致,那如果我们想动态匹配路径,做到路由与路径一致该怎么做呢?

这里我们捋一下我们的思维,其实我们只需要监听一下地址,然后跟我们的路由做一下匹配,最后路由变化的时候我们再重新渲染一下面包屑即可

监听一下地址
路由做一下匹配
路由变化=> 重新渲染面包屑

👉 对比watch和watchEffect实现

仅仅监听一下路由的话,其实watch和watchEffect都可以实现,本质上就是个监听的行为,我们先看看这两者实现的核心代码应该是啥样的

△ 正常我们两者之间应该如何去监听我们的路由

  • watch监听

通常我们用在需要在回调函数中执行复杂的逻辑,或者需要精确地控制回调函数的执行时机

<template>
   <div>watch</div>
</template>

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

const route = useRoute();

watch(() => route.path, (newPath, oldPath) => {
  console.log(`路由地址从 ${oldPath} 变为 ${newPath}`);
});
</script>
  • watchEffect监听

通常用在精确地监听特定的数据变化,或者在回调函数中执行复杂的逻辑

<template>
   <div>watch</div>
</template>
<script setup>
import { watchEffect } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

watchEffect(() => {
  const path = route.path;
  console.log(`当前路由地址为 ${path}`);
});
</script>

上面的代码十分简单,接下来我们就利用两者的监听来实现一下我们的面包屑功能,代码如下:

👉 watchEffect初步实现

接下来我们先试用watchEffect进行一个初步的实现,原理上应该是监听路由的变化,然后根据路由的变化来更新面包屑的内容

代码如下:


<template>
  <el-breadcrumb separator="/">
    <el-breadcrumb-item v-for="(val,index) in breadcrumbList" :key="val+''+index">
      <a :href="val.path">{{val.meta?.title}}</a>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>
<script setup>
import {getCurrentInstance,ref,onMounted,watch,watchEffect} from 'vue'
const { proxy } = getCurrentInstance()// 获取当前实例
const $route=proxy.$useRoute();
const breadcrumbList=ref([]);
const getBreadcrumb = () => {
  let matched = $route.matched.filter(item => item.meta && item.meta.title);
  const first = matched[0];
  if (!isDashboard(first)) {
    matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched);
  }
  breadcrumbList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false);
};

const isDashboard = (route) => {
  const name = route && route.name;
  if (!name) {
    return false;
  }
  return name.trim() === 'admin';
};

watchEffect(() => {
  const route = $route;
  // if you go to the redirect page, do not update the breadcrumbs
  if (route.path.startsWith('/redirect/')) {
    return;
  }
  getBreadcrumb();
});

getBreadcrumb();
</script>

再次点击我们发现watchEffect已经生效了,点击的时候也正常,那么watch其实也是可以实现的,我们也利用它来进行一下实现

👉 watch初步实现问题

利用watch实现的话,那他就应该是下面这样子:

<template>
  <el-breadcrumb separator="/">
    <el-breadcrumb-item v-for="(val,index) in breadcrumbList" :key="val+''+index">
      <a :href="val.path">{{val.meta?.title}}</a>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>
<script setup>
import {getCurrentInstance,ref,onMounted,watch,watchEffect} from 'vue'
const { proxy } = getCurrentInstance()// 获取当前实例
const $route=proxy.$useRoute();
const breadcrumbList=ref([]);
const getBreadcrumb = () => {
  let matched = $route.matched.filter(item => item.meta && item.meta.title);
  if (!isDashboard(first)) {
    matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched);
  }
  breadcrumbList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false);
};
const isDashboard = (route) => {
  const name = route && route.name;
  if (!name) {
    return false;
  }
  return name.trim() === 'admin';
};
watch(() => $route, (route) => {
  if (route.path.startsWith('/redirect/')) {
    return;
  }
  getBreadcrumb();
}, { immediate: true });
getBreadcrumb();
</script>

利用watch进行实现但是我们点击的时候路由却没发生变化,什么原因导致的呢

我们先来审查一下代码,watch和watchEffect类似代码,其实没区别,使用watchEffect来进行监听却没有出现这种问题,那为什么会出现这种情况呢

对比发现原因

🔺略微思考一下可以发现:
在监听路由的方式之中我们可以看到,我们监听的是$route,但是实际上我们点击的时候路由是发生了变化的,我们把写法写的更加原生一些试试

<script setup>
import {getCurrentInstance,ref,onMounted,watch,watchEffect} from 'vue'
const { proxy } = getCurrentInstance()// 获取当前实例
import { useRoute } from 'vue-router';
const route = useRoute();
const breadcrumbList=ref([]);
const getBreadcrumb = () => {
  let matched = route.matched.filter(item => item.meta && item.meta.title);
  const first = matched[0];
  if (!isDashboard(first)) {
    matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched);
  }
  breadcrumbList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false);
};

const isDashboard = (route) => {
  const name = route && route.name;
  if (!name) {
    return false;
  }
  return name.trim() === 'admin';
};
watch(() => route.path, (newPath, oldPath) => {
  console.log(`路由地址从 ${oldPath} 变为 ${newPath}`);
  if (route.path.startsWith('/redirect/')) {
    return;
  }
  getBreadcrumb();
});
getBreadcrumb();
</script>

再次点击我们发现,很奇怪的事发生了,这会我们点击面包屑的时候,路由已经可以正常发生改变了

👉结论:

上面watch我们监听的是route的引用,所以路由的变化并不会触发监听,因此我们需要监听route的引用,所以路由的变化并不会触发监听,因此我们需要监听route的值,而不是$route的引用

当然了,写法上watch对比watchEffect的话还是watchEffect更简洁一些,这里我们不需要监听太复杂的逻辑,使用watchEffect更好。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。