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

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

码农世界 2024-05-31 前端 76 次浏览 0个评论

文章目录

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

       

    实现思路

       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() 
        
        parentRoute = router.getRoutes().find(route => route.name === 'index');
         
        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 => {
      
        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 {
          item.children.forEach(Citem => {
            let routerChildren = { 
               
              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 params = JSON.parse(sessionStorage.getItem('NavList'));
        
       
      UpdataRouterList(params,Eligiblelimitsofauthority)
      
      aa =  GetPossibleDetails(Eligiblelimitsofauthority,params,aa)
      
      params.forEach(item => {
      
        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,
            }
          };
          
    else {
          item.children.forEach(Citem => {
            let routerChildren = { 
               
              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);
            });
          });
        }
      });
       
      if(aa){
         aa.map(item=>{
           if(item.component != undefined)
             list.push(item)
         })
      }
      //返回定义好的路由格式对象
     return list
    }

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

    //筛选出页面中出现可能是详情或者编辑的信息
    function UpdataRouterList(navlist:any,Eligiblelimitsofauthority:any) {
       
       navlist.map(item=>{
          if(item.slug.indexOf('create') != -1 || item.slug.indexOf('edit') != -1 || item.slug.indexOf('detail') != -1){
            
            Eligiblelimitsofauthority.push(item.slug)
          }
             >
          if(item.children){
            UpdataRouterList(item.children,Eligiblelimitsofauthority)
          }
       })
    }

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

    //根据传递过来的信息,筛选出存在权限的数据, 转换成路由信息 
    function GetPossibleDetails(data:object,navlist:object,aa:any,) {
      
      const module = import.meta.glob("../../views/**");
      
       navlist.map(item=>{
       
         data.map(ditem =>{
          
           if(item.web_path != null && ditem == `${item.slug}-create` || ditem == `${item.slug}-edit` ||  ditem == `${item.slug}-detail`){
            
            let list = {}
            
            let path  = ''
            if(item.web_path != null){
               
              path = item.web_path.slice(item.web_path.lastIndexOf('/') + 1 , item.web_path.length)
               
              switch ( ditem.slice(ditem.lastIndexOf('-') + 1 , ditem.length)) {
                case 'create':
                   //如果是新增
                  list = {
                    //定义新增页面跳转的路由路径,如: path是截取到的文件名:user  那就path最后就是 :/usercreate
                    path: '/'+path + 'create',
                    name: `${path}create`,
                    
                    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)
           }
         })
         
        if(item.children && item.parent_id == 0){
          GetPossibleDetails( data,item.children,aa)
         }
       })
       return aa
    }

    小结

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

    项目文件

转载请注明来自码农世界,本文标题:《Vue3:动态路由+子页面(新增、详情页)动态路由配置(代码全注释)》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,76人围观)参与讨论

还没有评论,来说两句吧...

Top