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

文章目录

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

实现思路

   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.最后添加到路由对象中的数据,最后一个对象就是新增的动态子页面路由

项目文件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

必应bing国内推广开户,全方位必应广告开户流程介绍!

在所有获客渠道中&#xff0c;搜索引擎广告成为企业扩大品牌影响力、精准触达目标客户的关键途径之一。作为全球领先的搜索引擎之一&#xff0c;必应&#xff08;Bing&#xff09;拥有庞大的用户群体和独特的市场优势&#xff0c;是企业不可忽视的营销阵地。云衔科技&#xff0…

Spring Web MVC介绍及详细教程

目录 1.什么是Spring Web MVC&#xff1f; 1.1 MVC定义 1.2 Spring MVC与MVC关系 2.为什么要学习Spring MVC 3.项目创建 4.Spring MVC连接 4.1 RequestMapping 4.2 PostMapping和GetMapping 5.Spring MVC参数获取 5.1 获取单个参数 5.2 获取多个参数 5.3 获取普通对…

echart 折线图tooltip

运行结果 代码 import { truncate, merge } from lodash; import { getBasePieOptions, getTooltipFormatter } from "*/money/utils";const colorArray [#1F8BFF, #EDBE75, #26E3F0, #AF8FFF, #61DDAA, #FD996A, #8367E0, #1AAF87]export function getLineOptions…

Prompt Engineering Guide

本文转载自&#xff1a;Prompt Engineering Guide https://www.promptingguide.ai/zh/introduction/basics 文章目录 提示工程简介1、基本概念1&#xff09;基础提示词2&#xff09;提示词格式 2、提示词要素3、设计提示的通用技巧从简单开始指令具体性避免不精确做还是不做&am…

【Spring security】【pig】Note03-pig token令牌解析器过程

&#x1f338;&#x1f338; pig token令牌解析器过程 &#x1f338;&#x1f338; pig后端源码 一、解析请求中的令牌值。 二、验证令牌 内省并验证给定的令牌&#xff0c;返回其属性。返回映射表示令牌有效。 /*** author lengleng* date 2019/2/1 扩展用户信息*/ publi…

互联网医院开发:引领智慧医疗新时代

随着科技的迅猛发展和互联网的普及&#xff0c;传统医疗模式正在迎来一场深刻的变革。互联网医院的崛起&#xff0c;打破了时间和空间的限制&#xff0c;为患者和医疗机构带来了更加便捷、高效、安全的医疗服务体验。本文将从技术角度深入探讨互联网医院的开发&#xff0c;包括…

货源困扰?没有货源也能做视频号电商,让你告别没有货源的困扰

大家好&#xff0c;我是电商花花。 目前视频号小店作为2024最有潜力的&#xff0c;最值得我们做的一个电话项目。 视频号小店作为一个新的直播电商平台&#xff0c;目前该项目还处于红利期间&#xff0c;流量大&#xff0c;商家少&#xff0c;现在入行的商家都可以享受到项目…

二级建造师考试工作年限怎么计算?中霖教育怎么样?

二级建造师考试对于工作年限有明确的要求&#xff0c;在计算二级建造师考试所需的工作年限时&#xff0c;考生需依据其所取得的教育类型来分别处理。 对于非全日制学历背景的考生&#xff0c;相关专业工作年限包括从获取规定学历之前直至报考当年年末所从事的该项工作的整个时…

网络安全技术与应用:远程控制与数据库安全

实验准备 软件&#xff1a;VMware Workstation Pro 虚拟机&#xff1a;Red Hat Enterprise Linux 7 服务器&#xff0c;Red Hat Enterprise Linux 7 客户端 网络模式&#xff1a;NAT模式 1、配置服务器及客户端网络 服务器IP 客户端IP 测试相互通信 在客户机上设置镜像&#…

Paddle 傅里叶变换基础及领域应用

Paddle 傅里叶变换基础及领域应用 1. 傅里叶变换基础 1.1 傅里叶变换简介 傅里叶变换是一种重要的信号处理技术&#xff0c;它可以将一个信号从时域转换到频域。在频域中&#xff0c;信号的频率特性更加明显&#xff0c;有利于分析和处理。傅里叶变换的基本思想是将一个信号…

网络原理3

运营商路由器&#xff0c;也可以把它当做一个NAT设备它就会对中间经过的数据包&#xff0c;进行网络地址转换当内网设备经过运营商路由器访问外网的时候就会把IP数据包中的源ip&#xff0c;替换成它自己的ip. 我的电脑要发送一个数据给cctalk服务器此时&#xff0c;我的电脑上就…

虎牙连续10个季度营收下滑,林松涛“三年计划“的游戏服务,没能扛起增收大旗

直播内卷的风&#xff0c;从大平台吹到了游戏直播的垂直赛道。 “游戏直播第一股”虎牙(NYSE&#xff1a;HUYA&#xff09;&#xff0c;已经连续10个季度营收下滑。 据虎牙最近发布的2024年一季报&#xff0c;当期营收15.04亿&#xff0c;同比减少23.1%。这已经是虎牙连续第1…

uniappx 安卓保活(多种技术;UTS版) Ba-KeepAlive-U

简介&#xff08;下载地址&#xff09; Ba-KeepAlive-U 是一款android原生保活插件&#xff0c;UTS版本&#xff08;同时支持uniapp和uniappx&#xff09;&#xff0c;支持市面上大部分机型&#xff0c;Android4.4到Android14&#xff08;**注意&#xff1a;**不保证支持所有机…

Android HAL到Framework

一、为什么需要Framwork? Framework实际上是⼀个应⽤程序的框架&#xff0c;提供了很多服务&#xff1a; 1、丰富⽽⼜可扩展的视图&#xff08;Views&#xff09;&#xff0c; 可以⽤来构建应⽤程序&#xff0c;它包括列表&#xff08;lists&#xff09;&#xff0c;⽹格&am…

【前端】深入浅出响应式布局

深入浅出前端响应式布局 在当今的网页设计与前端开发中&#xff0c;创建能够适应多种设备和屏幕尺寸的网页已成为必备技能。响应式布局&#xff08;Responsive Layout&#xff09;旨在通过灵活的设计和技术手段&#xff0c;让网页内容能够根据用户的设备环境自动调整&#xff…

Web 3D 框架简介

前言 3D游戏引擎的历史可以追溯到20世纪80年代末和90年代初。当时,计算机技术迅速发展,人们开始对图形和游戏感兴趣。以下是3D游戏引擎的历史故事: 早期引擎的诞生(1980-1990年代) 在这个时期,一些早期的3D游戏引擎开始出现。其中一个著名的例子是id Software开发的Do…

基于微信小程序的校园捐赠系统的设计与实现

校园捐赠系统是一种便捷的平台&#xff0c;为校园内的各种慈善活动提供支持和便利。通过该系统&#xff0c;学生、教职员工和校友可以方便地进行捐赠&#xff0c;并了解到相关的项目信息和捐助情况。本文将介绍一个基于Java后端和MySQL数据库的校园捐赠系统的设计与实现。 技术…

阿里云ubuntu 24 deb安装mysql5.7问题解决

阿里云最近有了ubuntu24&#xff0c;手欠直接选了24系统来试水&#xff0c;安装mysql这里遇到麻烦了 其它问题参考ubuntu22的即可&#xff0c;以下是3个新问题&#xff1a; 阿里云ubuntu 24 deb安装mysql5.7遇到的3个问题&#xff1a; 1&#xff09;libssl1.1 (&#xff1e; …

TG5032CKN是一种高稳定性晶体振荡器

TG5032CKN的输出频率范围为10 MHz至24 MHz&#xff0c;能够在-40C至105C的温度范围内工作&#xff0c;其频率/温度特性为0.110^-6 Max。这表明该设备具有很好的温度稳定性&#xff0c;适合在极端温度条件下使用。TG5032CKN的尺寸为5.03.21.65 mm&#xff0c;可以选择10针或4针封…

内网安全之搭建ADCS证书服务

在域控上安装ADCS服务时&#xff0c;默认会自动配置完LDAPS&#xff0c;如果不是在域控上安装ADCS服务&#xff0c;需要手动配置LDAPS 安装证书服务ADCS 打开服务器管理器——>添加角色和功能 选择“基于角色或基于功能的安装”选项&#xff0c;然后点击下一步 选择“从…