vue3:菜单、标签页和面包屑联动效果

文章目录

    • 1.整体思路
    • 2.实现过程

概要

提示:这里可以添加技术概要

例如:

openAI 的 GPT 大模型的发展历程。

1.整体思路

 在之前做的后台项目中,菜单、标签页和面包屑之间的联动,自己都是通过在路由前置守卫中,定义bus总线程通过.emit 和 .on 发送拿取需要的数据,然后再做一些自己想要的处理,实现自己想要的结果,后面在修改项目的时候就想要一中比较方便的办法,抛弃了通过bus总线程实现的方法。选择通过状态管理stroe来存储当前的路由信息控制三者的联动效果。

2.实现过程

1.创建你的组件文件,nav:菜单 、header:面包屑 、tabs:标签页,然后先把自己的基础页面信息。

2.将这些组件引入到view->index文件中

页面整体效果

2.创建store文件: index.ts  、user.ts 文件名字自己随便取,后面需要引入的时候不要把名称写错了

   store  //我习惯了命名 store  ,实际可以取名 pinia 因为用到的组件库就是这个

            * index

            * user

 index.ts

import {createPinia} from 'pinia'
let pinia= createPinia()
export default pinia

user.ts

import {defineStore} from 'pinia'
const useCounterStore = defineStore('appStore',{state :()=> ({menuiIsCollapse : false , //menu导航栏是否为展开NavList: [],  //menu导航栏的数据TabsList:[], //标签页的显示数据NowRouterPath :'' //当前路由}),actions : {//菜单栏的缩放updataMenuWidth(status:boolean){this.menuiIsCollapse = statusthis.menuiIsCollapse ? document.documentElement.style.setProperty('--el-aside-width', '64px') : document.documentElement.style.setProperty('--el-aside-width', '220px')},//第一次进入网站获取nav导航栏信息oneSetMenuList (obj:any | []){this.NavList = obj},//获取当前的路由信息getNowRouterPath(path:object){this.NowRouterPath = path.fullPaththis.screenTabsList(path)},//筛选tabs的数据显示 不存在就添加到 TabsList 中 screenTabsList(to_data:object){if(this.TabsList.length == 0){this.TabsList.push(to_data)}else{if(!this.TabsList.some(item => item.fullPath == to_data.fullPath)){this.TabsList.push(to_data)}}}},
})export default useCounterStore

3.创建router.ts文件,在src目录下新建router文件夹 - > 新建index.ts文件

import  { createRouter ,createWebHashHistory , createWebHistory } from "vue-router";
import pinia from '@/store'
import useUserStore from "@/store/user";
import { inject } from "vue";//必须 否则下面使用 _store 会报错 
useUserStore(pinia)const routes = [你自己的菜单数据]const router = createRouter({history : createWebHashHistory(),routes
})//前置路由守卫
router.beforeEach((to, from, next) => {//调用 store  在mian.ts中定义const _store = inject('store')//将当前路由信息传递给store->user.ts中的方法_store.getNowRouterPath(to)const isAuthenticated = checkIfUserIsAuthenticated();if (to.matched.some(record => record.meta.requiresAuth) && !isAuthenticated) {next({ name: 'login' });} else if (to.name === 'login' && isAuthenticated) {next({ name: 'index' });} else {next();}
});
function checkIfUserIsAuthenticated() {// 检查本地存储中的认证状态const isAuthenticated = localStorage.getItem('isAuthenticated');// 如果认证状态为true,则返回true;否则返回falsereturn isAuthenticated === 'true';
}
export default router

没有注册userUserStore出现的错误,大概意思就是当前没有组件生产,拿取不到Mian.ts中注册的pinia:

附上mian.ts文件

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from "./router";
import ElementPlus from 'element-plus'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import 'element-plus/dist/index.css'
import './assets/css/global.less';
import { createPinia } from "pinia";
import bus from "./mitt";
import useCounterStore from "@/store/user";
import { storeToRefs } from 'pinia';
const pinia = createPinia();const store = useCounterStore()
const storerefs = storeToRefs(store)//模拟数据
import { mockXHR } from "./mock/index";
mockXHR()const app = createApp(App)for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}app.use(pinia)
app.use(router)
app.use(ElementPlus)//VUE提供了provide 和 inject来解决了这个问题。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。app.provide('store_state', storerefs) //拿取到的pinia的state
app.provide('store', store) //拿到的整个pinia
app.provide('bus', bus) app.mount('#app')

4.菜单文件 nva->index.vue

<script lang="ts" setup>
import { onMounted, reactive, ref ,watch,inject} from "vue";
import { useRoute } from "vue-router";
import { get } from "../../axios/api";
import bus from "@/mitt";
const isCollapse = ref(true);
const router = useRoute();
let nowRouter = ref("");
let NavList = ref([]);
let childPath = ref([]);const store = inject('store')
const store_state = inject('store_state')//监听当前路由信息的变化 newVlaue是新值 ,vlaue 是变化之前的旧值
watch(()=>store_state.NowRouterPath.value,(newValue,value)=>{//判断当前的菜单数据信息中,是否包含新的路由数据,nowRouter赋值为新的路由,nav就会选中高亮显示NavList.value.map((item) => {newValue.indexOf(item.fullPath) == -1? item.children.map((child: any) => {nowRouter.value = newValue;router.fullPath.indexOf(newValue) !== -1 ? (nowRouter.value = newValue) : "";}): "";});
})onMounted(() => {
//这个只是判断请求的nav数据是否存在本地中,存在就不请求接口了if(sessionStorage.getItem('NavList')){NavList.value = JSON.parse(sessionStorage.getItem('NavList')) getNowPath()}else{getNavList()}
});//函数const getNavList = ()=>{let params = {token: localStorage.getItem("token"),};get("/api/getMenuList", params).then((res) => {NavList.value = res.data;store.oneSetMenuList(NavList);sessionStorage.setItem('NavList',JSON.stringify(NavList.value))getNowPath()});
}
const ClickToGo = (data)=>{}const getNowPath = () =>{NavList.value.map((item) => {item.children.length !== 0? item.children.map((child: any) => {childPath.value.push(child.path);}): childPath.value.push(item.path);});childPath.value.map((item) => {if (router.path.indexOf(item) !== -1) {nowRouter.value = item;}});
}
</script>
<template><el-menuclass="el-menu-vertical-demo":collapse="store_state.menuiIsCollapse.value":unique-opened="true":router="true" //为true的话,可以根据点击菜单中绑定的index是'/index'定义的路由,可点击直接跳转:default-active="nowRouter"background-color="#545c64"text-color="#fff"active-text-color="#ffd04b"><template v-for="(item, index) in NavList"><el-sub-menu v-if="item.children.length !== 0" :index="item.id"><template #title> //下拉菜单 <el-icon><component :is="item.web_icon" /></el-icon><span>{{ item.title }}</span></template>  //点击跳转菜单<el-menu-item-group v-for="(children, k) in item.children"><el-menu-item :index="children.path" @click="ClickToGo(children)">{{ children.title }}</el-menu-item></el-menu-item-group></el-sub-menu><el-menu-item v-else :index="item.path"><el-icon><component :is="item.web_icon" /></el-icon><template #title>{{ item.title }}</template></el-menu-item></template></el-menu>
</template>
<style scoped lang="less">
</style>

5.tab组件

<template><div class="container" ><el-tabsv-model="editableTabsValue"type="card"closable@tab-remove="removeTab"@tab-click="getRouter"><el-tab-panev-for="(item, index) in editableTabs":key="index":label="item.meta.name":name="item.fullPath"></el-tab-pane></el-tabs></div>
</template>
<script lang="ts" setup>
import { defineComponent, ref, onMounted ,inject,watch} from "vue";
import bus from "@/mitt";
import { useRouter } from "vue-router";const store = inject('store')const store_state = inject('store_state')//直接赋值为当前的路由 editableTabsValue 对应到 el-tab-pane中的:name 如果相同就会自动高亮显示let editableTabsValue = store_state.NowRouterPath;//pinia中保存的 tabs数据const editableTabs = store_state.TabsList// 页面加载时执行onMounted(() => {});// 移除选项卡const removeTab = (targetName: string) => {};// 点击选项卡const getRouter = (i: any) => {};
</script>

6.header 面包屑组件

<template><div class="header-box"><div class="header_item"><el-breadcrumb separator="/" class="header_left_title"> <el-breadcrumb-item :to="{ path: '/home' }">主页</el-breadcrumb-item><el-breadcrumb-item>{{ titleList.Pname }}</el-breadcrumb-item><el-breadcrumb-item v-if="titleList.name">{{titleList.name}}</el-breadcrumb-item></el-breadcrumb></div></div>
</template> 
<script  setup lang="ts">
import { onMounted, defineProps, provide, inject ,watchEffect ,watch} from "vue";
import { useRouter, useRoute } from "vue-router";
import { ref, reactive } from "vue";const router = useRoute();//面包屑显示数据let titleList = reactive({ Pname: "", name: "" });const store = inject('store')const store_state = inject('store_state')onMounted(() => {//拿取router 路由信息getMenuList(router.path);});//监听当前路由的信息变化
watch(()=>store_state.NowRouterPath.value,(newValue,value)=>{getMenuList(newValue);
})function getMenuList(path) {
//path:当前路由 ; 拿到nav菜单数据,对比是否能找到path对应的菜单信息,let menuList = JSON.parse(sessionStorage.getItem('NavList')) menuList.map((item) => {if (item.path !== path) {//判断是否存在children 可点击菜单item.children.length !== 0? item.children.map((child) => {//存入 下拉菜单的名称 和 筛选出的点击菜单名称if (child.path == path) {titleList.Pname = item.title;titleList.name = child.title;}}): "";} else {titleList.Pname = item.title;titleList.name = "";}});
}

如有写的不明确的地方可以提出来,或者大佬们有更好的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/809849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务面试题二

1.什么是雪崩 微服务之间相互调用&#xff0c;因为调用链中的一个服务故障&#xff0c;引起整个链路都无法访问的情况。 如何解决雪崩&#xff1f; 超时处理&#xff1a;请求超时就返回错误信息&#xff0c;不会无休止等待仓壁模式&#xff1a;限定每个业务能使用的线程数&a…

WPS的JS宏如何批量实现文字的超链接

表格中需要对文字进行超链接&#xff0c;每个链接指引到不同的地址。例如&#xff1a; 实现如下表格中&#xff0c;文件名称超级链接到对应的文件路径上&#xff0c;点击对应的文件名称&#xff0c;即可打开对应的文件。 序号文件名称文件路径1变更申请与处理表.xls文档\系统…

第十三届蓝桥杯省赛大学B组编程题(c++)

D.刷题统计 二分(AC): 注意:二分时右边界 right 的确定 #include<iostream> using namespace std; long long a,b,n; bool check(long long x){long long tx/7;x%7;long long temp0;if(x<5) tempx*a;else temp5*a(x-5)*b;long long cntt*(5*a2*b)temp;return cnt&g…

MySOL之旅--------MySQL数据库基础( 2 )

本篇碎碎念:尽自己最大的努力,直到筋疲力尽为止,加油 今日份励志文案: 别人都在前进,我为什么要停下 目录 补上一条博客缺失的内容 常用数据类型 数值类型&#xff1a; 字符串类型&#xff1a; 日期/时间类型&#xff1a; 二进制类型&#xff1a; 其他类型&#xff1a; …

抖音小店入驻有什么条件?资金少,没经验的普通人做得起吗?

大家好&#xff0c;我是电商花花。 在直播电商的推动下&#xff0c;抖音小店独特的电商模式下吸引着众多的商家&#xff0c;吸引着一波又一波的创业者入驻&#xff0c;想要在抖音小店上开垦出属于自己的电商净土。 想要入驻抖音小店还需要一些条件&#xff0c;然后才能入驻成…

Python机器学习学习线路

随着人工智能技术的飞速发展&#xff0c;机器学习已经成为计算机科学领域的热门话题。Python&#xff0c;作为一门功能强大且易于上手的编程语言&#xff0c;成为学习机器学习的理想选择。本文将为您介绍一条Python机器学习的学习线路&#xff0c;帮助您逐步掌握机器学习的基础…

ARM/X86+FPGA轨道交通/工程车辆行业的解决方案

深圳推出首条无人驾驶地铁—深圳地铁20号线&#xff0c;可以说是深圳地铁的一次开创性的突破。智能交通不断突破的背后&#xff0c;需要很严格的硬件软件等控制系 统&#xff1b;地铁无人驾驶意味着信号系统、通信系统、综合监控系统、站台屏蔽门工程等项目必须严格执行验收。…

ping命令返回无法访问目标主机和请求超时浅析

在日常经常用ping命令测试网络是否通信正常&#xff0c;使用ping命令时也经常会遇到这两种情况&#xff0c;那么表示网络出现了问题。 1、请求超时的原因 可以看到“请求超时”没有收到任何回复。要知道&#xff0c;IP数据报是有生存时间的&#xff0c;当其生存时间为零时就会…

goproxy一键安装脚本(稳定易用的proxy软件)

goproxy 官网 https://goproxy.cn/ go语言开发的简单易用高性能proxy 软件 #!/bin/bash # time: 2021-05-11 17:47:39 # by: Chen ##执行脚本需要传入网络设备名 ##例&#xff1a;sh goproxy-install.sh eth0# 0.安装必须要的依赖 yum install wget -y || apt install wget -y…

vue简单使用二(循环)

目录 属性绑定 if判断&#xff1a; for循环&#xff1a; 属性绑定 代码的形式来说明 三元表达式的写法&#xff1a; if判断&#xff1a; for循环&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"…

ActiveMQ + MQTT 集群搭建(虚机版本) + Springboot使用配置

文章目录 前言一、ActiveMQ、 MQTT是什么&#xff1f;1.ActiveMQ介绍2.MQTT介绍 二、集群搭建步骤1.下载apache-activemq-5.15.12-bin.tar.gz2.上传apache-activemq-5.15.12-bin.tar.gz到服务器并解压文件到文件夹clusters、master、slave三个文件夹下面形成三个节点&#xff0…

Win10下安装Anaconda

Anaconda是可以便捷获取包且对包能够进行管理&#xff0c;同时对环境可以统一管理的发行版本&#xff0c;它包含了conda、Python在内的超过180个科学包及其依赖项。 安装Anaconda Anaconda官方下载网址&#xff1a;https://www.anaconda.com/download 官网页面中&#xff0c…

Docker日志查看神器

探索Dozzle&#xff1a;简单实用的Docker日志查看工具 在容器化应用程序的开发和部署中&#xff0c;日志管理是至关重要的一环。为了便于查看和监控Docker容器的日志信息&#xff0c;开发人员和运维团队需要便捷的工具。Dozzle 就是这样一款简单实用的Docker日志查看工具&…

2024 Mathorcup高校数学建模挑战赛(A题)| PCI冲突问题 | 建模秘籍文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍团队独辟蹊径&#xff0c;以整数规划&#xff0c;多元回归等强大工具&#xff0c;构建了解决复杂问题的独特方案。深度学习, 混沌模型的妙用&#xff0c;为降低非法野生动物贸易提供新视角。通过综合分析&#xff0c;描绘出概率、…

基于springboot实现知识管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现知识管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个专门适应师生作业交流形式的网站。本文介绍了知识管理系统的开发全过程。通过分析企业对于知识管理系统的需求&#xff0c;创建了…

日出6万单!美区“开塞露”卖疯了,保健赛道正式起飞!

质疑养生&#xff0c;理解养生&#xff0c;加入养生&#xff01; 从保温杯里泡枸杞&#xff0c;到桌上摆满保健品&#xff0c;"养生"已经从一种模糊的概念转变为了生活中的刚需。在加班、熬夜、脱发这些"亚健康"标签的围绕下&#xff0c;年轻人开始重视自…

k8s基础入门

前言 开始学习K8S了&#xff0c;下面就是笔记整理 简介 k8s是谷歌开源得容器管理系统&#xff0c;主要功能包括 基于容器得应用部署&#xff0c;维护和滚动升级负载均衡和服务发现跨机器和跨地区得集群调度自动伸缩无状态服务和有状态服务广泛得Volume支持插件保持扩展性 …

ELFK的部署

目录 一、ELFK&#xff08;FilebeatELK&#xff09; 1. Filebeat的作用 2. ELFK工作流程 3. ELFK的部署 3.1 服务器配置 3.2 服务器环境 3.3 安装filebeat 3.4 修改filebeat主配置文件 3.5 在logstash组件所在节点&#xff08;apache节点&#xff09;上新建一个logstas…

如何管好地铁站见新质生产力 | 图扑数字孪生

智慧车站建设是现代交通领域的重要发展方向&#xff0c;旨在通过集成先进的信息技术&#xff0c;提升车站的运营效率、安全性及乘客体验。基于既有的综合监控技术&#xff0c;通过集成多种传感器和数据采集设备&#xff0c;实现对车站设备、环境、客流、人员等对象群的智能感知…

这样画箱线图,为你的SCI论文增色!

高级箱线图的绘制 下面的箱线图比较美观&#xff0c;非常适合数据量不大、且分布明显的时候使用。 在论文撰写中&#xff0c;图表的清晰和吸引人的展示方式是至关重要的。箱线图&#xff08;Whisker Plot&#xff09;是一种展示数据分布的经典工具&#xff0c;它不仅可以清楚地…