基于vue3异步组件、动态组件、vite批量导入实现路由权限动态管理(非addRoute方案)

本文介绍了在Vue3和Vite环境下,如何实现动态菜单权限管理。通过后端动态生成菜单和异步组件路径,结合`defineAsyncComponent`和`import.meta.glob`,实现根据用户角色加载相应路由的组件。同时,文章讨论了该方案的安全性,认为其与addRoute方式在安全性上相当,通常还会配合token校验增强安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发后台管理系统必备的需求:动态菜单权限管理、或者说路由权限动态管理
原理是通过addRoute实现路由权限控制,一般分为两种:

  1. 后端生成当前用户相应的路由后由前端(用 Vue Router 提供的API)addRoutes 动态加载路由
  2. 前端写好所有的路由,后端返回当前用户的角色,然后根据事先约定好的每个角色拥有哪些路由对角色的路由进行分配

这里就不具体论述了

这里介绍一个个人研究的,在vite+vue3下的动态菜单权限管理实现方案:
这是一个由后端动态菜单控制的解决方案,需要后端传异步组件的路径值
基于异步组件动态组件,而不是addRoute

1.使用vue3和vite语法

defineAsyncComponent是vue3定义异步组件的api
import.meta.glob是vite的批量导入语法

<script>
import { defineAsyncComponent } from "vue"
let modules = import.meta.glob("../dynamicComponent/**/*.vue")

2.管理系统左侧一般是树菜单,右侧是对应菜单内容

第一步肯定是请求后端获取左侧树菜单,点击单个树菜单右侧显示对应菜单内容
在上一步我们已经通过vite批量导入获取dynamicComponent文件夹下所有vue文件信息,在computed里面拼接动态组件路径即可

methods: {
    /** 获取树菜单数据 */
    async loadTreeData() {
      const { data: res } = await http.post("xxx")
      if (res.code === 0) {
        this.treedata = res.data
      }
    },
    /** 点击单个树菜单 */
    handleNodeClick(data) {
      this.currentNode = data
    },
 computed: {
    /** 动态组件 */
    dynamicComponent() {
      // 这里是点击树节点后树节点上的数据,vueUrl字段是跟后端沟通后返回的前端项目vue文件路径
      let filename = this.currentNode.vueUrl  
      return defineAsyncComponent(modules[`../dynamicComponent/${filename}.vue`])
    },
  },

3.动态组件

<div class="container">
    <div class="tree">
      ...
    </div>
    <div class="tree-right">
      <transition name="fade-transform" mode="out-in">
        <component
          v-if="dynamicComponent"
          :is="dynamicComponent"
        ></component>
      </transition>
    </div>
  </div>

可以看到核心代码思路其实是非常简单的,开发右侧内容区域的vue页面只需要放在dynamicComponent文件夹下,跟后端沟通好文件路径传值即可
比如后端传值user/common,对应前端项目vue文件路径是dynamicComponent/user/common.vue

安全性思考

dynamicComponent方案是具备安全性的,因为异步组件和动态组件只能通过后端传值的方式进行vue页面渲染,用户是不能通过路由进行页面访问的
假设网站攻击者可以伪造后端返回结果,那这种情况下当然可以访问到dynamicComponent的页面,但同理,这种也可以访问到addRoute的页面,所以这点上两者安全性是一样的,并且项目开发中一般还会有token请求头,页面数据请求会进行校验,所以综上dynamicComponent解决方案比较addRoute方案并没有安全性问题

### Vue 项目中批量导入动态路由实现方法 在 Vue 项目中,动态路由的管理是一个常见的需求,尤其是在需要根据用户权限动态加载路由的情况下。以下是关于如何通过批量化的方式实现动态路由的具体方法。 --- #### 1. **利用 Vite 或 Webpack 实现批量导入** Vite 和 Webpack 都提供了强大的模块解析能力,可以通过 `import.meta.glob`(Vite)或 `require.context`(Webpack)来实现文件路径的自动化扫描和注册。 ##### 使用 Vite 进行动态导入 Vite 提供了 `import.meta.glob` 方法,能够自动扫描指定目录下的所有 `.vue` 文件并将其作为组件引入: ```javascript // 批量导入 views 目录下所有的 .vue 组件 const modules = import.meta.glob(&#39;@/views/**/*.vue&#39;); const routes = Object.keys(modules).map(path => { const name = path.match(/\/([^/]+)\.vue$/)[1]; // 获取文件名作为路由名称 return { path: &#39;/&#39; + name, component: modules[path], name: name.charAt(0).toUpperCase() + name.slice(1), }; }); ``` 上述代码实现了对 `@/views` 路径下所有 `.vue` 文件的扫描,并自动生成对应的路由对象列表[^3]。 --- #### 2. **结合后端返回的数据生成动态路由** 实际应用中,通常需要依据后端接口返回的结果生成用户的个性化路由表。以下是一个完整的流程示例: ##### (1) 定义基础静态路由 这些路由通常是不需要权限校验的基础页面,比如登录页、404 页面等。 ```javascript const constantRoutes = [ { path: &#39;/login&#39;, component: () => import(&#39;@/views/login/index.vue&#39;), meta: { title: &#39;Login&#39; } }, { path: &#39;/404&#39;, component: () => import(&#39;@/views/error-page/404.vue&#39;), meta: { hidden: true } } ]; ``` ##### (2) 动态生成路由逻辑 假设后端返回了一个 JSON 数据结构描述用户的可用路由,可以根据该数据动态组装路由表。 ```javascript async function generateDynamicRoutes(userRoles) { const dynamicModules = import.meta.glob(&#39;@/views/modules/**/*.vue&#39;); let userRoutes = []; await Promise.all(Object.entries(dynamicModules).map(async ([path, loader]) => { const modulePathParts = path.split(&#39;/&#39;); const moduleName = modulePathParts[modulePathParts.length - 1].replace(&#39;.vue&#39;, &#39;&#39;); // 根据角色过滤符合条件的路由 if (userRoles.includes(moduleName)) { const routeComponent = await loader(); userRoutes.push({ path: `/${moduleName}`, component: routeComponent.default, name: moduleName, meta: { requiresAuth: true } }); } })); return userRoutes; } ``` 此处的关键在于使用 `Promise.all` 并结合异步加载器 (`loader`) 对应的角色筛选机制[^2]。 --- #### 3. **处理首次刷新时的 404 问题** 为了避免用户第一次访问系统时因动态路由尚未加载而跳转到 404 页面的情况,可以在初始化阶段手动添加默认的常驻路由。 ```javascript function addConstantRoutes(routerInstance) { constantRoutes.forEach(route => routerInstance.addRoute(route)); } export default async function setupRouter(app, router, store) { addConstantRoutes(router); try { const userRoles = await fetchUserRolesFromBackend(); // 假设这是获取用户角色的方法 const generatedRoutes = await generateDynamicRoutes(userRoles); generatedRoutes.forEach(route => router.addRoute(route)); app.use(router); } catch (error) { console.error(&#39;Failed to initialize dynamic routes:&#39;, error.message); } } ``` 这样可以确保即使在网络较慢或其他异常情况下,至少有部分基本功能可供正常使用[^1]。 --- #### 4. **优化性能与用户体验** 对于大规模的应用程序来说,合理运用懒加载技术至关重要。例如,在定义子路由时可以直接采用箭头函数包裹的形式触发按需加载行为: ```javascript { path: &#39;/dashboard&#39;, component: Layout, redirect: &#39;/dashboard/home&#39;, children: [ { path: &#39;home&#39;, component: () => import(&#39;@/views/dashboard/Home.vue&#39;) }, { path: &#39;settings&#39;, component: () => import(&#39;@/views/dashboard/Settings.vue&#39;) } ] } ``` 这种方式不仅减少了初始包体积,还提升了首屏渲染速度[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值