Vue3:menu导航栏出现多个同一跳转路径的菜单处理

news2024/11/26 9:46:50

文章目录

    • 需求整理
    • 实现思路
    • 实现过程

需求整理,实现思路

  最近公司想将之前老的项目整理出来,因为这个老项目内容太杂什么页面都往里面塞,导致菜单特别多,公司就像将这个老的项目迁出来,这个旧的项目本来是后端PHP写的。没有前后分离,导致现在项目需要修改东西,都是后端自己做,导致处理成本增加。所以提出来将项目迁离出来,前后端分离。我们想的是新需求页面做在新项目然后再新的项目中显示旧项目页面。

现在我就想的是如果在新项目中显示旧的项目页面,但是在vue中路由跳转一般都是一个页面对应一个路由,旧项目页面太多上百个,如果旧页面还没迁离出来,新的项目已经有上百个文件来显示页面,太冗余了,就想着用一个页面现在没有迁离出来的就页面。

实现过程

1.新项目中获取后端返回的页面权限以及页面的路由等信息

2.后端返回的新页面信息,因为现在后端接口还没有出,我就用的其他测试项目数据来实现,后续只要跟后端沟通让他们传递你想要的数据格式即可。

这是后端返回的新项目页面信息,正常展示即可

3.设计后端返回旧页面数据

一、动态路由渲染

 1.在我们拿到并处理数据后来实现动态绑定路由。定义路由格式然后绑定到你想要追加到路由中.

  public.ts

async function getUserAuthority(ids:any) {
 //获取用户菜单信息
   let userAuthority = null
   let NewList = null
   let params = {
    id:ids,
     permission_tree:1
   }
   await get('/system/user/detail',params).then(res=>{
    
      if(res.status_code == 200){
        userAuthority = res.data
        localStorage.setItem('userType',userAuthority.user_type)
        //将权限信息保存在本地中
        //自己编写的菜单信息,然后追加到后端返的菜单中
        let list =[{
          id: 116,
          children:[{
             id:1161,
             children:[],
             parent_id:116,
             name :'审单管理',
             web_path : `/gongdan`,
             links:'https://blog.csdn.net/qq_45061461?type=lately'
          }],
          web_icon:'el-icon-coin',
          name :'审单管理',
          web_path: null,
          
          },
          {
            id: 117,
            children:[{
              children:[],
              id:1171,
              parent_id:117,
              name :'换货留言列表',
              web_path : `/gongdan`,
              links:'https://so.csdn.net/so/search?q=vue3%3Amian,ts%E4%B8%AD%E8%8E%B7%E5%8F%96import.meta.glob&t=&u=&urw='
           }],
           web_icon:'el-icon-coin',
           name :'换货留言列表',
           web_path: null,
            
            }
        ]
        NewList = userAuthority.permissions.concat(list);

        sessionStorage.setItem('NavList',JSON.stringify(NewList))
      }
   })
   return NewList
}




function forEachRout  (){
  //创建路由格式对象
            
  const modules = import.meta.glob("../../views/**");//import.meta.glob来引入多个,单个的文件
  let params = JSON.parse(sessionStorage.getItem('NavList'));
  let list = [];
  params.forEach(item => {
    if (typeof item.web_path === 'string') {
      let routerChildrenOne = {
        path: item.web_path,
        name: `${item.web_path}/:${item.icon}`,
        component: modules[`../../views${item.web_path}/index.vue`],
        meta: {
          title: item.name,
          buts: [],
          requireAuth: true,
          keepAlive: true,
          externalLink: item.links,
        }
      };
      list.push(routerChildrenOne);
      let butOne = item.slug;
      routerChildrenOne.meta.buts.push(butOne);
    } else {
      item.children.forEach(Citem => {
        let routerChildren = { 
           //如上个函数中的 links就是跳转后端页面的路径, 如果有就改成动态参数路由 
          path:Citem.links ? `${Citem.web_path}/:${Citem.id}` :  Citem.web_path ,
          name: `${Citem.web_path}/:${Citem.id}`,
          component: modules[`../../views${Citem.web_path}/index.vue`],
          meta: {
            title: Citem.name,
            buts: [],
            requireAuth: true,
            keepAlive: true,
            externallink:Citem.links
          }
        };
        console.log('routerChildren',routerChildren);
        list.push(routerChildren);
        Citem.children.forEach(C_item_C => {
          let but = C_item_C.slug;
          routerChildren.meta.buts.push(but);
        });
      });
    }
  });
 return list
}



async function getRouteAddList() {
  let parentRoute = null;
  if (sessionStorage.getItem('NavList')) {
    let list =  forEachRout()
    //追加到 /index中的chilrend中
    parentRoute = router.getRoutes().find(route => route.name === 'index');
    list.forEach(item => {
      parentRoute.children.push(item);
    });
    //将自己更新好的路由独享添加到路由中
    router.addRoute(parentRoute);
  }
  return  parentRoute
}

//修改外部路径共用一个页面导致路由匹错误的问题
function  UpdataRouterObject(params:any){
  let ro = forEachRout()
  return ro.filter(item=> item.path == params.path)
}
2.将追加路由的函数完成返回结果 

mian.ts中:

//此函数完成返回后再更注册路由,否则在项目中刷新页面就会出现空白页的情况
PublicAPI.getRouteAddList().then(res=>{
  app.use(pinia)
  app.use(ElementPlus)
  app.use(router)
  app.mount('#app')
})
3.路由:router.ts
const routes = [
  {
    path: "/",
    name: 'login',
    component: () => import('@/views/login/index.vue'),
  },
  {
    path: "/index",
    name: 'index',
    component: () => import('@/views/index/index.vue'),
    children:[
    ],
  },
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

//路由前置守卫
router.beforeEach((to, from, next) => {
   //判断进入的路径中是否包含了/gongdan ,就说明是要跳转外部链接的页面
  if(to.fullPath.indexOf('/gongdan') !== -1){
       //此方法是传递你将进入的页面信息,然后再获取到之前自己定义的路由数据中对比,重新将正确的路由信息返回回来 再重置掉跳转错误的页面
        //如: path:/gongdan/:171  和 path:/gongdan/:161 他们跳转的路径不一样但是我需要那到的meta中的数据就一直会是 /gongdsn/:171中的meta所以要方法匹配重置      
      let params =  PublicAPI.UpdataRouterObject(to)
      to.name = params[0].name
      to.meta = params[0].meta
      next()
  }else{
      next();
  }
  _store.getNowRouterPath(to)
  

});

4.显示的页面

<script setup lang="ts">
import { onMounted } from "vue";
import useCurrentInstance from "@/hooks/useCurrentInstance";
const { proxy } = useCurrentInstance();

onMounted(()=>{})
</script>

<template>
   <div>
    //获取到路由传递过来的跳转路径
    <iframe :src="proxy.$route.meta.externallink" style="width: 100%; height: 100vh;"></iframe>
  </div>
</template>

<style scoped>

</style>

小提醒:登录页面后直接进入空白页但是页面上的路径是正确的跳转路径。

原因:项目启动的时候就会走mian.ts中的PublicAPI.getRouteAddList()方法但是该方法里面是获取本地中保存的menu菜单信息,所以本地没有的情况下动态添加的是空的,所以跳转页面会出现空白。

解决方法:

在登录的时候再调用一次该方法就行了 

const data = await post("/login",ruleForm);
          if(data.status_code == 200){
            let list = data.data
             localStorage.setItem("isAuthenticated", "true"); // 将用户认证状态保存在本地存储中
             for (const key in list) {
              if(key != 'expires_in'){
                localStorage.setItem(key,list[key])
              }
             }
             //获取权限
               proxy.$PublicAPI.getUserAuthority(list.user_id).then(res=>{
                    //获取请求动态路由
                   proxy.$PublicAPI.getRouteAddList()
                   //获取默认第一菜单的一个页面的路径进行跳转
                   proxy.$PublicAPI.getOnePagePath()
               })
              
          }
      } catch (error) {
        console.error("发生错误:", error);
      }

效果:

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

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

相关文章

【保姆级详细步骤教学用DOSBoxV0.74写出一个汇编语言程序输出Hello World!】

使用任何文本编辑器创建一个名为 HELLO.ASM 的文件&#xff0c;并将以下代码粘贴到文件中&#xff1a; .MODEL SMALL .STACK 100H.DATAMSG DB Hello, World!, $PROMPT DB 13, 10, Press any key to exit..., $.CODEMAIN PROCMOV AX, DATAMOV DS, AXMOV AH, 09HLEA DX, MSGINT …

用户页面触发点击事件和 js 执行点击事件的区别

文章目录 情景展示情况一&#xff1a;用户点击页面触发情况二&#xff1a;通过 js 触发点击 结果分析情况一情况二 其实这个谜底揭开之后&#xff0c;第一反应都是&#xff0c;哦~&#xff0c;非常简单&#xff0c;但是细节决定成败&#xff0c;我被这个细节毁掉了&#xff0c;…

docker资源限额

多数的应⽤场景要对Docker容器的运⾏内存进⾏限制&#xff0c;防⽌其使⽤过多的内存。 格式&#xff1a;-m或--memory 正常的内存大小 [rootadmin ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS …

硬件设计——滤波器设计_MIC用有源带通滤波器

“在已有的成熟稳定的滤波器基础上&#xff0c;根据业务需要对原设计进行优化调整以得到新的滤波器” 是滤波器设计的一种常用方法。 MIC用有源带通滤波器 介绍一种简单直观的带通滤波器以及计算过程&#xff0c;以作未来可参考的基线设计。该滤波器可用于音频信号&#xff0…

【算法】基础算法004之前缀和

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 本篇文章为大家带来前缀和…

【EI会议|投稿优惠】2024年物理化学与应用数学国际会议(IACPCAM 2024)

2024 International Conference on Physical Chemistry and Applied Mathematics 一、大会信息 会议名称&#xff1a;2024年物理化学与应用数学国际会议会议简称&#xff1a;IACPCAM 2024收录检索&#xff1a;提交Ei Compendex,CPCI,CNKI,Google Scholar等会议官网&#xff1a;…

基于树莓派的六足机器人方案设计+源代码+工程内容说明

文章目录 源代码下载地址项目介绍项目内容说明简单预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 项目内容说明 hardware为项目相关硬件设计 机械结构为六足机器人的3d建模工程&#xff0c;包括本体和云台遥控器在ESP32最小开发板上集成了MPU605…

Python面向对象编程思想的深入学习

魔术方法的使用 案例体验 class Student:def __init__(self, name, age):self.name nameself.age age# __str__魔术方法, 如果不去写这个方法&#xff0c;那么print输出的则是信息存储的内存地址。def __str__(self):return fStudent类对象&#xff0c;name:{self.name}, ag…

入门视频剪辑:视频合并不再难,批量嵌套合并的简单步骤

在数字媒体时代&#xff0c;视频剪辑已成为一项基本技能。无论是制作家庭电影、公司宣传片还是在线教育内容&#xff0c;视频剪辑都扮演着重要角色。对于初学者来说&#xff0c;视频剪辑可能看起来有些复杂&#xff0c;但掌握了正确的步骤和技巧后&#xff0c;你会发现它其实并…

【资源分享】PyCharm2020安装教程

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

了解外汇震荡类货币对特征与交易策略

外汇市场是全球最大的金融市场&#xff0c;每天的交易量超过6万亿美元。在这个市场上&#xff0c;货币对之间的价格变动反映了全球经济和政治动态。外汇货币对通常被分为三类&#xff1a;主要货币对、次要货币对和外来货币对。而在交易这些货币对时&#xff0c;市场表现通常分为…

MATLAB实现遗传算法优化同时取送货的车辆路径问题VRPSDP

同时取送货的车辆路径问题VRPSDP的数学模型如下: 模型假设 所有车辆的载重、容量等性能相同。每个客户的需求&#xff08;送货和取货量&#xff09;是已知的&#xff0c;且在服务过程中不会改变。车辆的行驶速度恒定&#xff0c;不考虑交通拥堵等实时路况变化。每个客户点只能…

记录一个RSA加密js逆向

network调试就不说了吧 pwd加密参数 搜索pwd参数定位逆向 可以看到有很多关键词 但是我们细心的朋友会发现加密函数关键字 encrypte 打上断点 调试 发现在断点处停止了 并且框选函数发现了一串加密值 虽然不一样但是大概率是这个 并且没你每次放置移开都会刷新 所以如果这个就是…

IP地址定位技术在网络安全中的作用

在当今数字化时代&#xff0c;网络安全已经成为企业、政府和个人面临的重要挑战之一。随着互联网的普及和网络攻击的增加&#xff0c;保护个人隐私和防止网络犯罪变得尤为重要。在这一背景下&#xff0c;IP地址定位技术作为网络安全的重要组成部分之一&#xff0c;发挥着关键作…

citylava:城市场景中VLMs的有效微调

citylava:城市场景中VLMs的有效微调 摘要IntroductionRelated WorkVision-Language ModelsVLMs in Driving Methodology CityLLaVA: Efficient Fine-Tuning for VLMs in City Scenario 摘要 在城市广阔且动态的场景中&#xff0c;交通安全描述与分析在从保险检查到事故预防的各…

C++——list和string

list与string 前言一、listlist.hList的节点类List的迭代器类list类list.h 完整实现 list.cppList的节点类List的迭代器类list类list.cpp 完整实现 二、stringstring.hstring.cpp 总结 前言 C容器的学习开始啦&#xff01; 大家先来学习list&#xff01; 紧接着string和vector…

如何查看打包后的jar包启动方法

背景 有时候我们在引用一个jar包的时候,想查看一个jar包的结构,这时候查看启动类就比较重要,因为一些关键配置是在启动类上的,这里教大家如何查看这个启动类(springboot项目) 步骤 首先打开jar包预览结构,可以使用解压缩工具直接双击打开或者预览结构 打开路径 META-INF/MA…

《挑战100个产品拆解:抖音》

抖音&#xff0c;作为当今社交媒体领域的明星产品&#xff0c;其背后的产品思维一直备受关注。在这篇文章中&#xff0c;我们将深入拆解抖音的产品思维&#xff0c;揭示其成功的秘密。 产品定位 1.产品是什么样的用户&#xff1a; 年轻人和青少年是抖音的主要用户群体。抖音…

Agent AI智能体:塑造未来社会的智慧力量

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f916; Agent AI智能体&#xff1a;塑造未来社会的智慧力量&#x1f3af; 引言&#x1f331; 智能体的未来角色预览&#x1f4bc; 行业革新者&#x1f31f; 创意合作者&#x1f6e1;️ 公共安全与环保&#x1f680; …

pycharm code行太长显示波浪线取消

实际操作如下&#xff1a;个人比较合适的位置为160,180时有点多 效果&#xff1a;