Vue3:动态路由+子页面(新增、详情页)动态路由配置(代码全注释)

news2024/11/24 9:36:06

文章目录

    • 实现思路
    • 调用后端接口获取用户权限
    • 获取页面权限动态绑定到路由对象中
    • 动态添加子页面路由
       

实现思路

   emm,项目中使用动态路由实现根据后端返回的用户详情信息,动态将该用户能够访问的页面信息,动态生成并且绑定到路由对象中。但是后端返回的不包含像是页面详情页,新增页的权限路由,如果前端在路由对象中写死的话,那每次进入页面都得判断是否将进入一个用户没有权限的页面,但是路由中有存在的。所以就想着自己能不能根据后端现有返回的信息,前端自己生成类似详情之类的动态路由。

调用后端接口获取用户页面权限动态绑定到路由对象中

1.获取用户权限

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  存入查询到该用户信息 
        userAuthority = res.data
        //模拟该页面是需要跳转其他项目的地址
        let list =[{
          id: 119,
          children:[{
             id:1191,
             children:[],
             parent_id:119,
             name :'审单管理',
             slug:'web-system-exchangegoods-management',
             web_path : `/gongdan`,
             links:'https://blog.csdn.net/qq_45061461?type=lately'
          }],
          slug:'web-system-examineadocument',
          web_icon:'el-icon-coin',
          name :'审单管理',
          web_path: null,
          },
          {
            id: 117,
            children:[{
              children:[],
              id:1171,
              parent_id:117,
              slug:'web-system-exchangegoods-management',
              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='
           }],
           slug:'web-system-exchangegoods',
           web_icon:'el-icon-coin',
           name :'换货留言列表',
           web_path: null,
            }
        ]
      
        //将后端返回的用户信息中的权限 和 自己定义的权限对象 合并一起
        NewList = userAuthority.permissions.concat(list);
        //将用户的权限信息保存本地中
        sessionStorage.setItem('NavList',JSON.stringify(NewList))
      }
   })
   return NewList
}

 2.用户登录请求信息 方法我就不写了

//调用定义的获取权限方法
proxy.$PublicAPI.getUserAuthority(list.user_id).then((res) => {
            //res就是上个方法中返回的权限信息 然后调用将路由添加入路由对象的方法
            proxy.$PublicAPI.getRouteAddList();
            //获取默认第一菜单的一个页面的路径进行跳转
            proxy.$PublicAPI.getOnePagePath();
          });

3.调用动态追加路由对象的方法

async function getRouteAddList() {
   <!--定义存放路由信息对象-->
  let parentRoute = null;
    <!--判断本地中是否存在权限信息-->
  if (sessionStorage.getItem('NavList')) {
    //list是 forEachRout方法返回的数据,将本地权限信息传入,根据信息生成路由对象格式数据
    let list =  forEachRout() 
    <!--router.getRoutes().find(route => route.name === 'index') 查找路由对象中的路由信息中name名为index的路由对象,name = index的路由对象path指向 index.vue 有显示页面元素的路由视图 <router-view /> -->
    parentRoute = router.getRoutes().find(route => route.name === 'index');
     <!--想自己生成的路由对象格式数据 追加到 /index中的chilrend中 -->
    list.forEach(item => {
      parentRoute.children.push(item);
    });
    <!--将定义好的路由数据格式对象添加到路由对象中-->
    router.addRoute(parentRoute);
  }
}

4.设计路由对象格式数据 forEachRout方法

function forEachRout  (){
  //存放已经设计好的路由对象
  let list = [] 
  //查找 ../../views/ 文件夹下所有的文件 views文件夹下是我存放的vue文件
  const module = import.meta.glob("../../views/**");
  <!-- 获取本地的权限信息 -->
  let params = JSON.parse(sessionStorage.getItem('NavList'));
  <!-- 循环遍历权限信息 -->
  params.forEach(item => {
  <!-- 判断权限信息中web_path 是否是为string,为string类型就是用户的页面权限 这是后端返回的 -->
    if (typeof item.web_path === 'string') {
    <!-- 设计路由对象格式信息 -->
      let routerChildrenOne = {
        path: item.web_path,
        name: `${item.web_path}`,
        component: module[`../../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 是判断是否需要跳转外部链接的对象,就是第一个截图中定义的两个权限数据对象 
-->
else {
      item.children.forEach(Citem => {
        let routerChildren = { 
           <!-- 判断对象中是否存在 links(跳转链接)属性,为存在的话,那么这个path将和其他同样存在links属性的对象公用一个页面(所有需要跳转外部的菜单都共同跳转这一个页面,所以这里使用了路由传参来确定点击他们不会只获取到最近的一个需要外部跳转的菜单,否则菜单中存在一个以上跳转外部菜单,无论点击哪一个都会跳转同一个外部链接。并菜单包含此path全部高亮),就会存在下方截图的错误-->
          path:Citem.links ? `${Citem.web_path}/:${Citem.id}` :  Citem.web_path ,
          name: `${Citem.web_path}`,
          component: module[`../../views${Citem.web_path}/index.vue`],
          meta: {
            title: Citem.name,
            buts: [],
            requireAuth: true,
            keepAlive: true,
            externallink:Citem.links
          }
        };
        list.push(routerChildren);
        Citem.children.forEach(C_item_C => {
          let but = C_item_C.slug;
          routerChildren.meta.buts.push(but);
        });
      });
    }
  });
  //返回定义好的路由格式对象
 return list
}

所以,在配置路由格式对象中外部跳转链接菜单通过动态路由传参来避免出现这个问题.到此菜单的动态路由已经配置完成。

动态添加子页面路由

但是我在想如果每个页面中都存在类似新增和详情的子页面,但是后端返回的信息中未包含,自己怎么也解决动态生成。于是就回到了,后端目前返回给我的权限信息,还有获取到veiws文件夹中的vue文件。

 1.后端返回的权限

2.veiws文件夹中已经存在的

3.实现,此方法就是 P4代码片段的方法 只不过增加了几个变量和调用了几个方法:

 新增变量名:Eligiblelimitsofauthority  , aa

 新增调用方法的方法名:UpdataRouterList 、GetPossibleDetails 

 已经底部retrun之前的判断对象是否存在component绑定的文件路由属性

function forEachRout  (){
  //存放已经设计好的路由对象
  let list = []
   <!-- 存放可能是新增页面,详情页面 和编辑页面的标识 -->
  let Eligiblelimitsofauthority = []
   <!-- 存放可能是新增页面,详情页面 和编辑页面的路由对象>
  let aa = [] 
  //查找 ../../views/ 文件夹下所有的文件 views文件夹下是我存放的vue文件
  const module = import.meta.glob("../../views/**");
  <!-- 获取本地的权限信息 -->
  let params = JSON.parse(sessionStorage.getItem('NavList'));
    
  <!-- 筛选出页面中出现可能是新增、详情或者编辑的信息 --> 
  UpdataRouterList(params,Eligiblelimitsofauthority)
  <!-- 根据传递过来的可能是详情或者编辑的信息,筛选出存在权限的数据,转换成路由格式对象 -->
  aa =  GetPossibleDetails(Eligiblelimitsofauthority,params,aa)


  <!-- 循环遍历权限信息 -->
  params.forEach(item => {
  <!-- 判断权限信息中web_path 是否是为string,为string类型就是用户的页面权限 这是后端返回的 -->
    if (typeof item.web_path === 'string') {
    <!-- 设计路由对象格式信息 -->
      let routerChildrenOne = {
        path: item.web_path,
        name: `${item.web_path}`,
        component: module[`../../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 是判断是否需要跳转外部链接的对象,就是第一个截图中定义的两个权限数据对象 
-->
else {
      item.children.forEach(Citem => {
        let routerChildren = { 
           <!-- 判断对象中是否存在 links(跳转链接)属性,为存在的话,那么这个path将和其他同样存在links属性的对象公用一个页面(所有需要跳转外部的菜单都共同跳转这一个页面,所以这里使用了路由传参来确定点击他们不会只获取到最近的一个需要外部跳转的菜单,否则菜单中存在一个以上跳转外部菜单,无论点击哪一个都会跳转同一个外部链接。并菜单包含此path全部高亮),就会存在下方截图的错误-->
          path:Citem.links ? `${Citem.web_path}/:${Citem.id}` :  Citem.web_path ,
          name: `${Citem.web_path}`,
          component: module[`../../views${Citem.web_path}/index.vue`],
          meta: {
            title: Citem.name,
            buts: [],
            requireAuth: true,
            keepAlive: true,
            externallink:Citem.links
          }
        };
        list.push(routerChildren);
        Citem.children.forEach(C_item_C => {
          let but = C_item_C.slug;
          routerChildren.meta.buts.push(but);
        });
      });
    }
  });
   <!-- 判断转换成路由格式数据中component有数据的对象,component不为空的时候就是标识项目中已经创建了这个新增,详情 或编辑的页面-->
  if(aa){
     aa.map(item=>{
       if(item.component != undefined)
         list.push(item)
     })
  }
  //返回定义好的路由格式对象
 return list
}

2.UpdataRouterList方法 筛选出页面中出现可能是详情或者编辑的信息

//筛选出页面中出现可能是详情或者编辑的信息
function UpdataRouterList(navlist:any,Eligiblelimitsofauthority:any) {
   <!-- 循环传过来的本地权限数据对象中包含了 'create','edit' 和 'detail'的标识 -->
   navlist.map(item=>{
      if(item.slug.indexOf('create') != -1 || item.slug.indexOf('edit') != -1 || item.slug.indexOf('detail') != -1){
        <!-- 存入到可能包含新增,详情,编辑的标识数组中 -->
        Eligiblelimitsofauthority.push(item.slug)
      }
         <!-- 判断是否还有子数据,第一次循环的是下拉菜单 第二次循环的是下拉菜单中的点击跳转页面的菜单,第三次循环点击跳转页面的菜单中的 按钮权限,主要是拿到按钮权限菜单  这里是只有二级菜单,所以循环了三次,如果有多级也会一直循环下去,知道children中没有数据-->>
      if(item.children){
        UpdataRouterList(item.children,Eligiblelimitsofauthority)
      }
   })
}

3.GetPossibleDetails 根据传递过来的信息,筛选出存在权限的数据, 转换成路由信息,因为如果在本地中已经定义了全部的页面新增,详情,编辑等页面,但是咱们还是需要根据后端返回的权限中,判断咱们是否注册该页面的路由。

//根据传递过来的信息,筛选出存在权限的数据, 转换成路由信息 
function GetPossibleDetails(data:object,navlist:object,aa:any,) {
  <!-- 获取项目中views文件夹下的所有vue文件 -->
  const module = import.meta.glob("../../views/**");
  <!-- 遍历本地中的权限数据-->
   navlist.map(item=>{
   <!-- 传递过来的可能是 新增,详情,编辑的权限标识 -->
     data.map(ditem =>{
      <!-- 判断 item.web_path是否不为空,如果为空的话表明菜单是下拉菜单就不做操作 item.slug :这个菜单的标识 如:web-users 就是表示user(用户)菜单 -->
       if(item.web_path != null && ditem == `${item.slug}-create` || ditem == `${item.slug}-edit` ||  ditem == `${item.slug}-detail`){
        <!-- 存放定义的路由数据格式对象 -->
        let list = {}
        <!-- 截取item.we_path 菜单路径处理后的值,如:/user 我拿取user 后面作为/veiws/user,匹配views下的user文件夹 所以这里获取的是该菜单存放的文件夹名称 -->
        let path  = ''
        if(item.web_path != null){
           <!-- 截取文件夹名称 -->
          path = item.web_path.slice(item.web_path.lastIndexOf('/') + 1 , item.web_path.length)
           <!-- ditem是方法接收传递过来可能是新增,编辑,详情的权限标识数组,判断最后的-符号的后面是 'create':新增 ,'edit' :编辑 'detail':详情 -->
          switch ( ditem.slice(ditem.lastIndexOf('-') + 1 , ditem.length)) {
            case 'create':
               //如果是新增
              list = {
                //定义新增页面跳转的路由路径,如: path是截取到的文件名:user  那就path最后就是 :/usercreate
                path: '/'+path + 'create',
                name: `${path}create`,
                <!-- 匹配本地vue文件中是否包含 module:views下所有的vue文件,path:文件夹名称,item.web_path:vue文件名称 -->
                component: module[`../../views/${path}${item.web_path}create.vue`],
                meta: {
                  title: '新建' + item.name ,
                  buts: [],
                  requireAuth: true,
                  keepAlive: true,
                  externalLink: item.links,
                }
              }
              break;
            case 'edit':
              console.log('item-edit',item);
              list = {
                path: '/'+path + 'edit',
                name: `${path}edit`,
                component: module[`../../views/${path}${item.web_path}edit.vue`],
                meta: {
                  title: item.name  + '编辑' ,
                  buts: [],
                  requireAuth: true,
                  keepAlive: true,
                  externalLink: item.links,
                }
              }
            break;
          case 'detail':
            list = {
              path: '/'+path + 'detail',
              name: `${path}detail`,
              component: module[`../../views/${path}${item.web_path}detail.vue`],
              meta: {
                title:  item.name + '详情'  ,
                buts: [],
                requireAuth: true,
                keepAlive: true,
                externalLink: item.links,
              }
            }
            break;
         }
        }
        aa.push(list)
       }
     })
     <!-- 判断菜单中的chidren是否存在数据,如果没有存在就表明是一级点击跳转菜单,parent_id :0 表示的是菜单 -->
    if(item.children && item.parent_id == 0){
      GetPossibleDetails( data,item.children,aa)
     }
   })
   return aa
}

小结

1.最后添加到路由对象中的数据,最后一个对象就是新增的动态子页面路由

项目文件

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

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

相关文章

【leetcode面试经典150题】-80. 删除有序数组中的重复项 II

【leetcode面试经典150题】-80. 删除有序数组中的重复项 II 1 题目介绍2 个人解题思路2.1 代码2.2 思路 3 官方题解 1 题目介绍 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组…

MongoDB基础入门到深入(七)建模、调优

文章目录 系列文章索引十一、MongoDB开发规范十二、MongoDB调优1、三大导致MongoDB性能不佳的原因2、影响MongoDB性能的因素3、MongoDB性能监控工具&#xff08;1&#xff09;mongostat&#xff08;2&#xff09;mongotop&#xff08;3&#xff09;Profiler模块&#xff08;4&a…

2024电工杯数学建模竞赛选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B<A&#xff0c;开放度&#xff1a;A<B。 以下为AB题选题建议及初步分析&#xff1a; A题&#xff1a;园区微电网风光储协调优化配置 题目描述&#xff1a; 园区微电网由风光发电和主电网联合为负荷供电&#xff0c;需要…

18kw 机架式液冷负载的使用方法有哪些?

机架式液冷负载是一种高效、节能的散热设备&#xff0c;广泛应用于数据中心、服务器房等场所。它通过将冷却液循环流动&#xff0c;将热量从负载设备带走&#xff0c;实现设备的稳定运行。以下是18kw机架式液冷负载的使用方法&#xff1a; 1. 安装前准备&#xff1a;在安装机架…

【Linux】-Spark分布式内存计算集群部署[20]

注意&#xff1a; 本节的操作&#xff0c;需要前置准备好Hadoop生态集群&#xff0c;请先部署好Hadoop环境 简介 Spark是一款分布式内存计算引擎&#xff0c;可以支持海量数据的分布式计算。 Spark在大数据体系是明星产品&#xff0c;作为最新一代的综合计算引擎&#xff0c…

对于高速信号完整性,一块聊聊啊(8)

什么是Df和Dk 介电常数( D k )、介质损耗( D f ) 介电常数&#xff1a;材料如果在受到外部电场作用时能够储存电能&#xff0c;就称为“电介质”。比如说&#xff0c;电容可以存储电荷&#xff0c;而当电容平板中间填充有介质时&#xff0c;存储的电荷会更多。介电常数越大&a…

Nginx配置全攻略:掌握Nginx的高级技巧,提升你的Web服务器性能!

作为一个资深的技术人员&#xff0c;全面理解Nginx的配置是非常重要的。本文将详细介绍Nginx配置文件的各个部分&#xff0c;包括介绍、命令或语法、主要作用以及使用方法等。 一、Nginx简介 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件代理服务器&#xff0c;它的…

解锁链上创意新时代,Story Protocol 如何颠覆内容创作与知识产权管理?

随着生成式人工智能&#xff08;AIGC&#xff09;的兴起&#xff0c;用户生产内容的浪潮正迅速席卷全球。然而&#xff0c;去中心化的链上生态并未彻底解决创作知识产权纠纷频发的难题。作为一个颇具潜力的平台&#xff0c;Story Protocol 正在引领内容创作的变革&#xff0c;为…

SaToken+SpringBoot+Redis前后端分离登录认证

目录 前言一、创建工程项目&#x1f38d;1.1 创建后端工程1.2 创建前端工程 二、业务代码&#x1f38a;后端代码前端代码 三、测试参考资料 前言 Sa-Token 是一款 Java 语言的权限认证框架&#xff0c;提供了灵活、高效、易用的权限认证和会话管理功能。它是 SpringBoot、Spri…

每日AIGC最新进展(9):定制化多主题文本到视频的生成、3D动漫角色生成、具有多种几何形状和纹理细节的3D高斯引导服装合成

Diffusion Models专栏文章汇总:入门与实战 DisenStudio: Customized Multi-subject Text-to-Video Generation with Disentangled Spatial Control 本文提出了一个名为DisenStudio的框架,用于定制化多主题文本到视频的生成。该框架旨在解决现有文本到视频生成模型在处理多主题…

vue从入门到精通(四):MVVM模型

一,MVVM MVVM&#xff08;Model–view–viewmodel&#xff09;是一种软件架构模式。MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑&#xff08;数据模型&#xff09;的开发分离开来。详见MVVM 二,Vue中的MVVM Vue虽然没有完全遵循 MVVM 模型&#xff0c;但是 Vue 的设…

C# GetManifestResourceStream 获取项目资源为null解决方案(亲测)

GetManifestResourceStream 获取项目资源为null 使用Stream s assembly.GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name resourceName) 获取资源文件&#xff0c;返回流为null&#xff0c;如图所示&#xff1a; 解决方案 设置资源文件的 属性&…

Jenkins 构建 Maven 项目:项目和服务器在一起的情况

bash.sh内容 #!/bin/bash#删除历史数据 rm -rf ruoyi-admin.jar# appname$1 appnamevideo.xxxxx.com #获取传入的参数 echo "arg:$appname"#获取正在运行的jar包pid # pidps -ef | grep $1 | grep java -jar | awk {printf $2} pidps -ef | grep $appname | grep ja…

【Qt】如何优雅的进行界面布局

文章目录 1 :peach:写在前面:peach:2 :peach:垂直布局:peach:3 :peach:水平布局:peach:4 :peach:网格布局:peach:5 :peach:表单布局:peach: 1 &#x1f351;写在前面&#x1f351; 之前使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的。也就是每个控件所在…

ElasticSearch IK分词器的安装、词典扩展与停用

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;云原生与服务部署-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 ​编辑 1. 前言 2. IK分词器安装 3. IK分词器词典扩展与停用 4. 总…

基于Python flask的豆瓣电影数据分析可视化系统,功能多,LSTM算法+注意力机制实现情感分析,准确率高达85%

研究背景 随着数字化时代的到来&#xff0c;电影产业正迎来新的发展机遇和挑战。基于Python Flask的豆瓣电影数据分析可视化系统的研究背景凸显了对电影数据的深度分析和情感挖掘的需求。该系统功能丰富&#xff0c;不仅实现了多样化的数据分析功能&#xff0c;还结合了LSTM算…

算法2:滑动窗口(上)

文章目录 长度最小子数组无重复字符的最长子串[最大连续 1 的个数III](https://leetcode.cn/problems/max-consecutive-ones-iii/description/)将x减到0的最小操作数 长度最小子数组 class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {in…

线段(线性dp)

题目链接&#xff1a;[TJOI2007] 线段 - 洛谷 思路&#xff1a; f[i][0]表示走完第i行且停在第i行的左端点最少用的步数 f[i][1]同理&#xff0c;停在右端点的最少步数。 那么转移就很简单了&#xff0c;走完当前行且停到左端点&#xff0c;那么一定是从右端点过来的&#x…

torch配置时出现问题

torch配置时出现如下问题&#xff1a; 可能原因&#xff1a; 1、下载的whl文件中python版本与本机上的python版本不匹配&#xff1b; 2、上图中的文件是64位的&#xff0c;而本机python是32位的&#xff0c;也无法匹配&#xff1b; 3、cuda的版本不匹配。