vue2 动态路由的实现

news2024/12/21 10:29:02

概述
一般情况下,路由都是前端约定好的,但是每当项目发布上线,或者客户需求新的页面的时候,都需要做出路由改变。这样运维就可以现场支持,方便做出可操作的中户中台,来管理我们的中心项目登录及权限,路由等方面;

这样就必须使用动态生成路由,由后台返回具体的路由结构体;我这边是这样模拟的;

[
  {
    "id": 612,
    "menuName": "测试数据1",
    "pid": 0,
    "url": "HOME_REMOTE_INTERROGATION",
    "menuType": "1",
    "visible": 1,
    "isRefresh": 1,
    "perms": null,
    "projectSign": "pt-osc",
    "bind": null,
    "sort": 0,
    "children": []
  },
  {
    "id": 605,
    "menuName": "测试数据2",
    "pid": 0,
    "url": "HOME_WARNING_MANAGEMENT",
    "menuType": "1",
    "visible": 1,
    "isRefresh": 1,
    "perms": null,
    "projectSign": "pt-osc",
    "bind": null,
    "sort": 0,
    "children": [
      {
        "id": 653,
        "menuName": "测试数据1子集",
        "pid": 605,
        "url": "/region",
        "menuType": "0",
        "visible": 1,
        "isRefresh": 1,
        "perms": null,
        "projectSign": "pt-osc",
        "bind": null,
        "sort": null,
        "children": []
      },
      {
        "id": 652,
        "menuName": "测试数据1子集",
        "pid": 605,
        "url": "/roomList",
        "menuType": "0",
        "visible": 1,
        "isRefresh": 1,
        "perms": null,
        "projectSign": "pt-osc",
        "bind": null,
        "sort": null,
        "children": []
      }
    ]
  },
]

这个值是跟后台约定好的,通过这个值来寻找总路由的父路由路由匹配;(也许现在很懵,继续往下看!)

在这里插入图片描述

第一步首先需要将项目需要的路由在此文件处理一边,创建 router.js 文件,内容如下(下方文件代码可复制使用,针对不同数据结果做出调整即可):

引入路由 vue 组件(望理解打码!)
在这里插入图片描述

// 首先需要将项目中 所有路由准备好!(包括所有父路由,子路由)   这里只是测试数据,真实场景需要定义所有的路由!
const routerArr = [
{
    path: '/home',
    name: 'OneStop',
    component: OneStop,
    meta: {
      urlType: 'BCDEFG',
    },
    children: [
      {
        path: '/one',
        name: 'One',
        component: Special,
      },
      {
        path: '/test1',
        name: 'test1',
        component: () =>
          import('@/views/oneStop/components/Test1.vue'),
        meta: {
          title: '测试页面1',
        },
      },
      {
        path: '/test2',
        name: 'test2',
        component: () =>
          import('@/views/oneStop/components/Test2.vue'),
        meta: {
          title: '随笔写2',
        },
      },
    ],
  },
  {
    path: '/monitor',
    name: 'monitorIndex',
    redirect: '/monitor/region',
    component: () => import('@/views/monitor/index.vue'),
    meta: {
      title: '的撒发达',
      urlType: 'CDFGHFADF',
    },
    children: [
      {
        path: '/region',
        name: 'region',
        component: () => import('@/views/monitor/components/testTwo.vue'),
        meta: {
          title: '第二个路由1',
        },
      },
      {
        path: '/roomList',
        name: 'roomList',
        component: () =>
          import('@/views/monitor/components/testTwo.vue'),
        meta: {
          title: '第二个路由2',
        },
      },
    ],
  },
]

// 这个方法是使用递归的形式   作用:将所有嵌套的子路由进行打平,  且把 path路径当作key值进行约定!
function flatRouters(data) {
  const config = {}
  data.forEach((rItem) => {
    let childrenConfig = {}
    // 先判断是否有 子集
    if (rItem.children?.length) {
      childrenConfig = flatRouters(rItem.children)
    }
    if (!rItem.meta || !rItem.meta.urlType)
      config[rItem.path] = {
        ...rItem,
        children: [],
      }
    Object.assign(config, childrenConfig)
  })

  return config
}

// 声明变量接受 打平 后的子路由对象数据
const confing = flatRouters([...routerArr])
const _routerPack = {}

// 将所有父路由的 urlType 作为key值, value等于本身
routerArr.forEach((item) => {
  _routerPack[item.meta.urlType] = {
    ...item,
    children: [],
  }
})

// 在处理过后的 config 对象中 匹配数据      拿传入的路径,去匹配config的数据,取出config的数据。
function setRouter(menu) {
  const keys = Object.keys(confing)
  const menuKey = keys.find((key) => key.includes(menu.url))
  if (menuKey) {
    const dataR = confing[menu.url]
    if (dataR) return dataR
  }
  return false
}

// 递归的去匹配路由数据  (也就是去匹配 config 中的数据取出来生成新数组)
function getRouter(menuData) {
  const rArr = []
  const typeKeys = Object.keys(_routerPack)
  menuData.forEach((menuItem) => {
    // 判断是否为大类
    if (menuItem.menuType === '1') {
      const key = typeKeys.find((k) => k.includes(menuItem.url))
      if (key) {
        const children = menuItem.children ? getRouter(menuItem.children) : []
        const rCun = rArr.find((item) => item.meta.urlType === key)
        if (rCun) {
          const chil = children.filter((item) => {
            return rCun.children.find((i) => i.name !== item.name)
          })
          rCun.children.push(...chil)
        } else {
          const menu = _routerPack[key]
          menu.children = children
          rArr.push(menu)
        }
      }
    } else {
      // 此时为 路由数据
      // 先判断 是否存在子集
      const childrenArr = []
      if (menuItem.children.length) {
        menuItem.children.forEach((childrenItem) => {
          const cItem = setRouter(childrenItem)
          if (cItem) childrenArr.push(cItem)
        })
      }
      const rItem = setRouter(menuItem)
      if (rItem) {
        rItem.children = []
        rItem.children.push(...childrenArr)
        rArr.push(rItem)
      }
    }
  })
  return rArr
}


// 调用方法
function addRouter() {
  const projectData = JSON.parse(sessionStorage.getItem('projectData'))
  if (projectData) {
    const permList = projectData.permList ?? []
    return getRouter(permList)
  }
  return []
}

export { routerArr, confing, addRouter }

第二步路由总文件中,也就是 目录 router 下的 index.js文件(内容约定如下):

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/login'
// 引入刚才声明的方法
import { addRouter, routerArr } from './router'

Vue.use(VueRouter)

let addRoute = []

// 因为做了配置  根据isDynamicRouting值,是否动态路由,是的话调用addRouter方法, 不是直接赋值原本路由即可!
if (window.ENV.isDynamicRouting) {
  addRoute = addRouter()
} else {
  addRoute = routerArr
}

// 这些是固定路由,登陆页面,404页面
const routes = [
  {
    path: '/login',
    name: 'Login',
    components: {
      default: Login,
      child: null,
    },
  },
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/mock/videoPlayer',
    name: 'videoPlayer',
    component: () => import('@/views/mock/videoPlayer'),
  },
]

// 导出方法  注册路由
export function createRouter(r = []) {
  return new VueRouter({
    mode: 'history',
    base: import.meta.env.VITE_PUBLIC_PATH || '/',
    scrollBehavior: () => ({ y: 0 }),
    routes: [...r, ...routes],
  })
}

const router = createRouter(addRoute)

// 全局导航守卫
router.beforeEach(async (to, form, next) => {
  const { token } = sessionStorage
  const { sfzh } = to.query
  if (!token && to.name !== 'Login') {
    if (window.ENV.isDynamicRouting) {
      // 这里是为避免重复路由的问题
      const newRouter = createRouter()
      router.matcher = newRouter.matcher
    }
    if (sfzh) next({ name: 'Login', query: { ...to.query, toPath: to.path } })
    next('/login')
  }
  next()
})

export default router

然后再总入口文件main.js中 注册即可(这里只粘贴相关代码):

import router from './router'

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app')

最后一步:
登录成功后记得要将 最上方等你们约定数据结构放到 缓存当中哦!因为这里:

在这里插入图片描述

// 动态路由
 if (window.ENV.isDynamicRouting) {
   const router = addRouter()
   router.forEach((item) => {
     this.$router.addRoute(item)
   })
 }

注意:isDynamicRouting 这个值决定了是否使用动态路由,声明在全局里面!

退出时需要置空路由,重新指定:
在这里插入图片描述

到此就结束啦!对你有帮助的话留下你的收藏点赞哦!谢谢!

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

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

相关文章

华为云前台展示公网访问需要购买EIP,EIP流量走向

华为云前台网络(VPC,安全组,EIP) 1.EIP网段是从哪里划分的? 管理员在后台Service_OM已设置 Service_OM-网络资源-外部网络-创建外部网络基本信息:配置参数:*名称 public*网络类型 LOCAL 不带标签 类似开…

树状数组+概率论,ABC380G - Another Shuffle Window

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 G - Another Shuffle Window 二、解题报告 1、思路分析 不难用树状数组计…

LSTM(长短期记忆网络)详解

1️⃣ LSTM介绍 标准的RNN存在梯度消失和梯度爆炸问题,无法捕捉长期依赖关系。那么如何理解这个长期依赖关系呢? 例如,有一个语言模型基于先前的词来预测下一个词,我们有一句话 “the clouds are in the sky”,基于&…

麒麟nginx配置

一、配置负载均衡 配置麒麟的yum源 vim /etc/yum.repos.d/kylin_aarch64.repo Copy 删除原来内容,写入如下yum源 [ks10-adv-os] name Kylin Linux Advanced Server 10 - Os baseurl http://update.cs2c.com.cn:8080/NS/V10/V10SP2/os/adv/lic/base/aarch64/ …

AI工业大模型报告:体系架构、关键技术与典型应用

研究意义 随着新一代人工智能的发展, 大模型(如 GPT-4o 等)凭借大规模训练数据、网络参数和算 力涌现出强大的生成能力、泛化能力和自然交互能力, 展现出改变工业世界的巨大潜力. 尽管大模型 已在自然语言等多个领域取得突破性进展, 但其在工业应用中的…

华为ensp实验二--mux vlan的应用

一、实验内容 1.实验要求: 在交换机上创建三个vlan,vlan10、vlan20、vlan100,将vlan100设置为mux-vlan,将vlan10设置为group vlan,将vlan20设置为separate vlan;实现vlan10的设备在局域网内可以进行互通&…

【微软:多模态基础模型】(1)从专家到通用助手

欢迎关注【youcans的AGI学习笔记】原创作品 【微软:多模态基础模型】(1)从专家到通用助手 【微软:多模态基础模型】(2)视觉理解 【微软:多模态基础模型】(3)视觉生成 【微…

学习threejs,使用第一视角控制器FirstPersonControls控制相机

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️第一视角控制器FirstPerson…

GitLab 降级安装出现 500 错误,如何解决?

本文分享 GitLab 中文版在降级的过程中出现 500 错误的修复方法。 写在前面 强烈不建议大家自行降级,如果真有降级需求,要么自己能力过硬,要么寻求专业服务【https://dl.gitlab.cn/cm33bsfv】,要不出问题很麻烦! 问…

《Representing Scenes asNeural Radiance Fields for View Synthesis》论文解析——NeRF

一、论文简介 NeRF这篇论文提出了一种通过优化一个连续的5D体积场景函数来合成复杂场景新视图的方法。该算法使用一个全连接的深度网络来表示场景,输入是单一连续的5D坐标(空间位置和观察方向),输出是该位置的体积密度和依赖于观察…

精通rust宏系列教程-调试过程宏

Rust过程性宏是该语言最令人兴奋的特性之一。它们让你能够在编译时注入代码,但与单态泛型所使用的方法不同。使用非常特殊的包(crate),让你可以完全从头开始构建新代码。本文从简单示例开始,逐步分解,也会详…

035_Progress_Dialog_in_Matlab中的进度条对话框

进度条 概念 在使用Matlab开发界面时,有一个很好用的工具就是进度条。在计算过程中,为用户提供计算进度的反馈是改善用户体验的重要手段。 一项进行的计算任务,如果其总体进度是比较容易量化,则可以按照0%~100%的方式&#xff0…

动态规划:计算技术中的核心【精确与效率并存】

写在前面 博客来源:翻译自youtube高赞技术视频,并精加工和细化。 适合阅读:想要搞懂动态规划的小伙伴~ 动态规划是一项杰出的计算技术,它既保留了穷举法的精确性,又吸收了贪心算法的高效率。 它主要应用于两个领域…

【JavaSE线程知识总结】

多线程 一.创建线程1.多线程创建方式一(Thread)2.多线程创键方式二(Runnable)3.线程创建方式三 二.线程安全问题解决办法1.使用同步代码块synchornized 2 .使用Lock解决线程安全问题 三.总结 线程就是程序内部的一条执行流程 一.创建线程 常用的方法 Thread.currentThread()…

Leetcode - 周赛423

目录 一,3349. 检测相邻递增子数组 I 二,3350. 检测相邻递增子数组 II 三,3351. 好子序列的元素之和 四,3352. 统计小于 N 的 K 可约简整数 一,3349. 检测相邻递增子数组 I 本题有两种做法: 先求出递增…

boost之property

简介 property在boost.graph中有使用,用于表示点属性或者边属性 结构 #mermaid-svg-56YI0wFLPH0wixrJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-56YI0wFLPH0wixrJ .error-icon{fill:#552222;}#me…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-25

文件下载与邀请翻译者 学习英特尔开发手册,最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册,会是一件耗时费力的工作。如果有愿意和我一起来做这件事的,那么&#xff…

paddle表格识别数据制作

数据格式 其中主要数据有两个一个表格结构的检测框&#xff0c;一个是tokens&#xff0c;注意的地方是 1、只能使用双引号&#xff0c;单引号不行 2、使用带引号的地方是tokens里面 "<tr>", "<td", " colspan2", ">",&quo…

Java 全栈知识体系

包含: Java 基础, Java 部分源码, JVM, Spring, Spring Boot, Spring Cloud, 数据库原理, MySQL, ElasticSearch, MongoDB, Docker, k8s, CI&CD, Linux, DevOps, 分布式, 中间件, 开发工具, Git, IDE, 源码阅读&#xff0c;读书笔记, 开源项目...

WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇

WebRTC视频 01 - 视频采集整体架构 WebRTC视频 02 - 视频采集类 VideoCaptureModule WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇 WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇&#xff08;本文&#xff09; WebRTC视频 05 - 视频采集类 VideoCaptureDS 下篇 一、前言…