vue-router + element-plus实现面包屑导航栏和路由标签栏

这篇具有很好参考价值的文章主要介绍了vue-router + element-plus实现面包屑导航栏和路由标签栏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

效果预览(服务器已过期,不支持预览)

首先,先解释一下什么是面包屑导航栏和路由标签栏。

如下图所示,面包屑导航栏就是展示当前所处路由信息和父辈路由信息的导航栏,它的作用是提示用户当前页面所在位置;路由标签栏就类似于浏览器的标签栏,每个标签对应一个路由页面,点击该标签可以进入该路由页面。

在这里解释一下,我所说的父辈路由是父路由的超集,对于一个子路由,它的父路由、它的父路由的父路由、它的父路由的父路由的父路由…都属于它的父辈路由。我也不知道这种叫法是否规范,反正大家理解这个意思就行。
vue-router + element-plus实现面包屑导航栏和路由标签栏

然后展示一下效果:
这是我自己做的一个基于vue3+typescript的网站,后端是用golang写的,网站有查询微博、百度、凤凰历史热搜的功能,以及上传图片、创建相册、分享相册等云图床相关功能。这是网站预览地址和gitee仓库地址。(ps:此网站并不是一个demo,而是具有完整前后端交互和一定功能的网站,需要注册并登陆才能使用,注册很简单,只需要设置用户名、账号、密码即可。也可登陆测试账号: admin,密码: 123456。 但如果有超过五个人同时登陆这个测试账号,那么后者会把前者挤下去,当然这种概率很小罢了。这里附上后端仓库地址,我是用go写的,大概总共二十多个接口吧)

vue-router + element-plus实现面包屑导航栏和路由标签栏

对于侧边导航栏如何实现的,请移步这篇文章:vue-router + element-plus实现多层级路由的动态展示

在本文章中,我主要讲解如何实现面包屑导航栏和路由标签栏。

面包屑导航栏的实现

先讲一下大体思路:

  • 首先弄清楚面包屑导航栏要展示哪些数据
  • 然后想办法获取这些数据
  • 最后把数据应用到组件中

首先,面包屑展示哪些数据?

路由的结构其实就是一棵树,没有子路由的路由对应树中的一个叶子节点,面包屑导航栏中要展示的就是这个当前页面对应的子路由、以及该子路由所有的父辈路由

为了方便说明,我举个例子,现在有一个网页的路由结构如下图中所示,假如当前我们处于localhost:8080/earth/asia/china页面,那么当前页面的子路由就是中国,它有两个父辈路由分别是亚洲和地球,所以我们要在面包屑中展示的信息就是 “地球 / 亚洲 / 中国”
vue-router + element-plus实现面包屑导航栏和路由标签栏
然后,如何获取这些数据?

在一棵树中,要获得一个叶子节点的所有父辈节点信息,可以从根节点开始进行dfs深度优先搜索,在搜索的过程中存一下在当前分支上搜过的路径,如果遇到叶子节点就把路径保存起来作为结果。

这种方法是一种可行方案,但其实还有更简单的方法。我们可以把这棵树线索化,在每个节点中存一下父节点的信息,那么就可以根据该节点直接获得父节点,进而获得父节点的父节点,父节点的父节点的父节点…,递归操作,就可以该节点获得所有父辈节点信息。

下面是从我的网站源码/src/router/index.ts中截取出来的代码,可以看到我在meta里自定义了一个parentRouteName属性,这个属性就是线索属性,我们可以借助这个属性获取该路由的父路由。

{
	path: 'weibo',
	name: 'Weibo',
	component: () => import('../views/hot/Weibo.vue'),
	meta: {
		description: '微博热搜查询',
		parentRouteName: "Hot",
		showInAside: true,
		showInHeader: true
	}
},

下面这个函数的作用是获取某个路由的所有父辈路由信息,参数name是子路由的名称,参数routes是路由数组,返回值是一个string数组,它的值是 […, 爷爷路由名称, 父亲路由名称, 子路由名称]。

依然沿用上面的例子,假如我们传入的name属性等于’china’,那么函数的返回值是[‘earth’, ‘asia’, ‘china’]

// 获取面包屑的路由名称数组
export function getNames(name: string, routes:RouteRecordNormalized[]): string[]{
    let names: string[] = []
    // 使用while循环进行递归操作,直至遍历到最顶级的父辈路由,然后退出循环
    while(true){
        names.push(name)
        let route = getRouteByName(name, routes) as RouteRecordNormalized
        let parentRoute = getRouteByName(route.meta?.parentRouteName as string, routes)
        if(parentRoute){
            name = parentRoute.name as string
            continue
        } 
        else{
            break
        }
    }
    return names.reverse()
}

最后,将数据写入element-plus提供的面包屑组件

获取了数据之后,接下来要做的就很简单了,只需要把数据写到面包屑组件里做展示即可,如下面代码所示。

还需要添加一个路由守卫,在每次路由跳转后都要更新面包屑里的数据。其实可以写成计算属性的,毕竟route对象和router对象都是响应式的。

下面的代码是从源码/src/components/layout/Header.vue里截出来的,想看完整的代码请访问gitee仓库地址。

<template>
	<el-breadcrumb separator="/">
	  <el-breadcrumb-item 
	    v-for="description,index in descriptions"
	    :key="description"
	    :to="{ name: routeNames[index] }"
	    class="breadcrumb-item"
	  >
	    {{description}}
	  </el-breadcrumb-item>
	</el-breadcrumb>
</template>
<script setup lang="ts">
import { getNames, getDescriptions, getRouteByName } from '../../util/handleRoutes'
import {useRouter, useRoute, RouteRecordNormalized} from 'vue-router'
const router = useRouter()
const route = useRoute()
let descriptions = ref<string[]>([])
let routeNames = ref<string[]>([])

//获取面包屑的数据
routeNames.value = getNames(route.name as string, router.getRoutes()) 
descriptions.value = getDescriptions(routeNames.value, router.getRoutes())

//在每次路由跳转后,更新面包屑的数据
router.afterEach((to, from) => {
  //不知道为什么,进入页面时,会有两次路由跳转,route.name为空
  if(!route.name){
    console.log(route.name, route.meta)
    return
  }

  routeNames.value = getNames(route.name as string, router.getRoutes())
  descriptions.value = getDescriptions(routeNames.value, router.getRoutes())
})
</script>

路由标签栏的实现

和上面的思路类似,要实现路由标签栏,我们也是分三个步骤:

  • 首先,考虑路由标签栏需要哪些数据
  • 然后,如何获取这些数据
  • 最后,如何把这些应用到组件并展示出来

首先,路由标签栏需要哪些数据?

类比一下,浏览器标签栏存放的是曾经访问过的网页,那么很显然路由标签栏需要的数据就是曾经访问过的路由页面。

然后,如何获取访问过的路由页面?

我是这样做的,在pinia里定义一个routerStore,里面有个visitedRoutes属性,用来存放所有访问过的路由,它的初始值只包含首页对应的路由。

import { defineStore } from "pinia"
import { RouteRecordNormalized} from "vue-router"
import { router } from "../router"
import { getRouteByName } from "../util/handleRoutes"
let defaultRoute = getRouteByName('Home', router.getRoutes()) as RouteRecordNormalized
let visitedRoutes = [defaultRoute]
export const useRouteStore = defineStore('route', {
  // 推荐使用 完整类型推断的箭头函数
  state: () => {
    return {
      visitedRoutes
    }
  },
})

添加一个路由守卫,在每次路由跳转后,如果进的路由不存在于visitedRoutes,那么把这个路由添加到visitedRoutes里面。

router.afterEach((to, from) => {
  if(!to.meta.showInHeader){
    return
  }
  let result = routeStore.visitedRoutes.find(val => val.name == to.name)
  if(!result){
    routeStore.visitedRoutes.push(getRouteByName(to.name as string, router.getRoutes()) as RouteRecordNormalized)
  }
})

最后,把历史访问数据应用到组件里

这一步比面包屑的最后一步要复杂一些,因为路由标签的交互比较多,当路由标签被点击时,需要跳转到相应路由。当路由标签被关闭时,如果当前页面并不是要关闭的路由标签,那么直接关闭即可;如果当前页面时要关闭的路由标签,那么需要进行路由跳转,跳转到首页。
下面的代码是从源码/src/components/layout/Header.vue里截出来的,想看完整的代码请访问gitee仓库地址。文章来源地址https://www.toymoban.com/news/detail-422070.html

<template>
  <div class="header-part-two">
    <el-tag
      v-for="visitedRoute in routeStore.visitedRoutes"
      :key="visitedRoute.name"
      :closable="visitedRoute.name != 'Home'"
      :disable-transitions="false"
      @close="handleClose(visitedRoute.name as string)"
      @click="goToRoute(visitedRoute.name as string)"
      @click.middle="handleClose(visitedRoute.name as string)"
      :class="{'active-tag': isActive(visitedRoute.name as string)}"
    >
      {{ visitedRoute.meta?.description }}
    </el-tag>
  </div>
</template>
<script>
import {useRouter, useRoute, RouteRecordNormalized} from 'vue-router'
import { useRouteStore } from '../../store/route'
const routeStore = useRouteStore()
const router = useRouter()
const route = useRoute()
// 跳转
function goToRoute(name:string){
  router.push({name})
}
function isActive(name:string){
  return name == route.name 
}
// 关闭
function handleClose(routeName: string){
  if (routeName === 'Home') {
    return
  }
  routeStore.visitedRoutes = routeStore.visitedRoutes.filter(val => val.name != routeName)
  if(route.name == routeName){
    router.push('/')
  }
}
</script>

到了这里,关于vue-router + element-plus实现面包屑导航栏和路由标签栏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • NodeJS+Vue+Element-Ui/Plus+Axios+Vue-router+vuex 详细下载、安装、创建项目、引入

    1.下载过程默认下一步 (1)这个是官网全版目录,下载太慢(一般下载不了);但是它写了所有nodejs和npm相互对应的版本,可以以此为参考、防止版本不对应; NodeJS各个历史版本下载 https://nodejs.org/zh-cn/download/releases/ (2)这里有一个快速下载地址,只有16.18.1这个版本,但这

    2023年04月18日
    浏览(55)
  • vue3 element-plus 实现图片预览

    element-plus下有这么一个组件 el-image-viewer /,但是这个组件是没写在文档上面的,像普通组件一样使用即可 可以通过点击按钮实现图片预览,而非el-image组件只能通过点击图片实现预览 2.1封装组件 2.3组件使用 在需要使用的地方引入,然后使用即可,这不是重点,每个人使用的

    2024年02月15日
    浏览(59)
  • (二) Vue3 + Element-Plus 实现动态菜单栏

    系列介绍:Vue3 + Vite + TS 从零开始学习 项目搭建:(一) Vue3 + Vite + TS 项目搭建 实现动态菜单栏:(二) Vue3 + Element-Plus 实现动态菜单栏 实现动态面包屑:(三) Vue3 + Element-Plus 实现动态面包屑 实现动态标签页:(四) Vue3 + Element-Plus 实现动态标签页 实现动态主题色切换(demo):(五)

    2023年04月23日
    浏览(59)
  • Vue3+element-plus实现后台管理系统

     环境:node.js软件 、Vs code、vite、elemnt-plus、windicss(样式框架)     1、首先,使用npm 命令构建项目( vscode安装的插件 vscode中文显示插件   2、高亮提示插件volar   3、vue 3 sni 代码提示) 快速上手 | Vue.js    a. npm -v 查看node.js 版本    b.  npm  config get registry   查看注册镜像是

    2024年02月09日
    浏览(55)
  • Vue3 element-plus表单嵌套表格实现动态表单验证

    部分效果图如下: 另表格有添加和删除按钮,点击提交进行表单验证。 首先data格式必须是对象包裹数组 给表单绑定form数据 表格绑定tableData数据 给表单项增加验证规则 rules对应data rules对象,prop对应表单字段(注意是表格里每一行对应的字段 forms.tableData[下标].key) prop的关

    2024年02月14日
    浏览(44)
  • Vue + Element-Plus + SpringBoot + WebSocket实现简易网络聊天室

    项目流程图 1. 前端搭建:         前端用Vue+Element-Plus 来搭建,由登录页面和聊天页面组成 1.1 登录页面         由一个昵称输入框组成,用户输入自己的昵称若昵称和别的用户不重复,则可进入聊天室,否则提示错误并请重新输入。         这段代码是一个Vue.js组件的

    2024年02月03日
    浏览(66)
  • Vue3使用element-plus实现弹窗效果-demo

    2024年02月13日
    浏览(52)
  • 基于springboot+Vue+ Element-Plus+mysql实现学生宿舍管理系统

    系统主要功能: 系统管理员:用户管理(学生信息、宿管员信息)、宿舍管理(楼宇信息、房间信息)、信息管理(公告信息、报修信息)、申请管理(调宿申请)、访客管理、水电费管理、卫生检查、个人信息 宿管员:用户管理(学生信息)、宿舍管理(楼宇信息、房间

    2024年02月06日
    浏览(52)
  • vue3+element-plus+el-image实现点击按钮预览大图

    需求:点击某个按钮实现el-image中预览大图的效果 官方文档:以下是官方的写法,并不能达到我们的要求,官方实现的功能是点击图片达到预览大图的效果。如果你的按钮就是图片,也可以达到目前的功能 el-image-viewer组件是element官方的组件,只是文档中没有写出来,这个组

    2024年02月12日
    浏览(58)
  • vue3+element-plus 通过v-infinite实现下拉滚动无限加载

    v-infinite官网 v-infinite-scroll无限滚动组件使用详解  官网给到的基础案例: 自己写了一个简单的demo: 当使用v-infinite时,控制台会报错:  原因: 官方上的Issues解释是需要nextTick()之后再去显示 解决方法是组件挂载完成再去显示el-select组件 所以在上面demo中select组件加了v-if,

    2024年02月09日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包