Code前端首页关于Code前端联系我们

一、vue-router auto-routes 到底是什么?

terry 3周前 (09-05) 阅读数 44 #Vue
文章标签 router;autoroutes

p>不少用 Vue 开发项目的同学,在处理路由时总会头疼:页面一多,手动写大量路由配置既费时间又容易出错,这时候“vue-router auto-routes”相关的自动路由方案,就成了很多人想了解的“提效神器”,可它到底是什么?普通项目里怎么实现自动路由配置?今天咱们把这些问题拆开来聊聊。

auto-routes 不是 vue-router 官方内置功能,而是开发者基于 vue-router 原理,实现的“自动扫描文件并生成路由配置”的技术方案,核心逻辑很简单:让“文件结构”直接对应“路由结构”(pages 文件夹里的文件路径,自动转成路由的 path),不用手动写 routes 数组。

举个例子:Nuxt.js 的路由系统就是典型的自动路由——pages/index.vue 对应路由 ,pages/user/[id].vue 对应 /user/:id,要是普通 Vue 项目想实现类似逻辑,就需要借助 Webpack 的 require.context 或者 Vite 的 glob 导入,扫描指定目录下的组件文件,再根据文件路径生成路由规则。

为什么项目需要自动路由?

手动写路由配置的痛点,就是自动路由的价值所在:

  1. 效率爆炸式提升
    大型项目动辄几十个页面,手动写 pathcomponent 不仅慢,还容易漏写、写错,自动路由让“新增页面”变成“按规则放文件”——只要文件丢对地方,路由自动生效,开发速度直接起飞。

  2. 维护性肉眼可见变好
    路由规则和文件结构一一对应,新人看文件路径就懂路由逻辑,比如看到 pages/article/edit.vue,马上能猜到路由是 /article/edit,不用翻冗长的 routes.js

  3. 把人为错误扼杀在摇篮
    手动配置时,很容易把 component 路径写错(比如少个 ),或者嵌套路由 children 漏写,自动路由靠“约定+程序扫描”,从源头减少这类低级错误。

普通 Vue 项目怎么实现 auto-routes?(分 Vite、Webpack 场景)

自动路由的核心是“扫描文件 → 解析路径 → 生成路由配置”,不同构建工具(Vite/Webpack)扫描文件的 API 不同,实现方式也有差异。

(一)Vite 项目实现自动路由

Vite 提供 import.meta.glob 函数,能批量导入指定目录的文件,步骤如下:

约定目录结构(核心!)

把页面组件丢到 src/pages 目录,让“文件路径”对应“路由 path”:

  • src/pages/index.vue → 路由 path: '/'
  • src/pages/about.vue → 路由 path: '/about'
  • src/pages/user/[id].vue → 路由 path: '/user/:id'(动态路由)
  • 嵌套路由可借助“布局组件”,src/pages/dashboard/__layout.vue(里面放 <router-view>),该目录下的其他页面作为子路由。

写自动生成路由的逻辑

src/router/index.js 里写这段代码:

import { createRouter, createWebHistory } from 'vue-router'
// 扫描 pages 下所有 .vue 文件(**表示递归子目录)
const pages = import.meta.glob('../pages/**/*.vue') 
function generateRoutes() {
  const routes = []
  for (const filePath in pages) {
    // 第一步:处理文件路径 → 转成路由 path
    let routePath = filePath.replace('../pages', '') // 去掉前缀
    routePath = routePath.replace(/\.vue$/, '')      // 去掉 .vue 后缀
    // 处理动态路由:把 [id] 转成 :id
    routePath = routePath.replace(/\[(\w+)\]/g, ':$1') 
    // 处理首页:pages/index.vue → 路由 /
    if (routePath === '/index') {
      routePath = '/'
    }
    // 第二步:导入组件(pages[filePath] 是动态导入函数)
    const component = pages[filePath]
    // 第三步:push 到路由数组
    routes.push({
      path: routePath,
      component: component
    })
  }
  return routes
}
const router = createRouter({
  history: createWebHistory(),
  routes: generateRoutes()
})
export default router

(二)Webpack 项目实现自动路由

Webpack 用 require.context 扫描文件,思路和 Vite 一致,只是 API 不同:

同样约定目录结构(和 Vite 通用,方便跨工具迁移)

还是把页面丢 src/pages,路径规则和上面一样。

写路由生成逻辑

src/router/index.js 里:

import { createRouter, createWebHistory } from 'vue-router'
// 扫描 pages 目录(参数:目录、是否递归、匹配规则)
const requirePage = require.context('../pages', true, /\.vue$/) 
function generateRoutes() {
  const routes = []
  requirePage.keys().forEach(filePath => {
    // 处理文件路径 → 转成路由 path
    let routePath = filePath.replace('./', '') // 去掉 ./ 前缀
    routePath = routePath.replace(/\.vue$/, '')// 去掉 .vue 后缀
    routePath = routePath.replace(/\[(\w+)\]/g, ':$1') // 动态路由
    // 处理首页:pages/index.vue → 路由 /
    if (routePath === 'index') {
      routePath = '/'
    } else {
      routePath = `/${routePath}` // 非首页加 / 前缀
    }
    // 导入组件(requirePage(filePath).default 是组件)
    const component = requirePage(filePath).default
    routes.push({
      path: routePath,
      component: component
    })
  })
  return routes
}
const router = createRouter({
  history: createWebHistory(),
  routes: generateRoutes()
})
export default router

自动路由的进阶玩法:嵌套路由、布局组件、路由守卫

前面实现了“基础自动路由”,但实际项目还有嵌套路由、统一布局、路由守卫等需求,得再加点逻辑。

(一)嵌套路由 + 布局组件

Dashboard 模块”需要统一侧边栏布局,可约定:用 __layout.vue 当布局组件(里面放 <router-view>),该目录下的其他页面作为子路由。

示例目录

  • src/pages/dashboard/__layout.vue(布局组件,含 <router-view>
  • src/pages/dashboard/index.vue(Dashboard 首页,对应 /dashboard
  • src/pages/dashboard/settings.vue(对应 /dashboard/settings

代码逻辑(以 Vite 为例,修改 generateRoutes

function generateRoutes() {
  const routes = []
  const layoutMap = new Map() // 存“布局路径 → 布局组件”
  for (const filePath in pages) {
    const fileRelativePath = filePath.replace('../pages', '')
    // 第一步:识别布局文件(以 __layout.vue 
    if (fileRelativePath.endsWith('__layout.vue')) {
      const layoutPath = fileRelativePath.replace('/__layout.vue', '')
      layoutMap.set(layoutPath, pages[filePath]) // 存布局组件
      continue // 布局文件本身不作为路由,只当父路由的 component
    }
    // 第二步:处理普通页面
    let routePath = fileRelativePath.replace(/\.vue$/, '')
    routePath = routePath.replace(/\[(\w+)\]/g, ':$1')
    if (routePath === '/index') routePath = '/'
    // 第三步:找当前页面属于哪个布局的子路由
    let parentLayout = ''
    for (const layoutPath of layoutMap.keys()) {
      if (routePath.startsWith(layoutPath)) {
        parentLayout = layoutPath
        break
      }
    }
    if (parentLayout) {
      // 子路由:给父路由加 children
      const parentRoute = routes.find(route => route.path === parentLayout)
      const childPath = routePath.replace(parentLayout, '') // 子路径,/dashboard/settings → 去掉 dashboard 后是 /settings
      if (parentRoute) {
        parentRoute.children = parentRoute.children || []
        parentRoute.children.push({ path: childPath, component: pages[filePath] })
      } else {
        // 父路由还没创建,先创建(用布局组件)
        routes.push({
          path: parentLayout,
          component: layoutMap.get(parentLayout),
          children: [{ path: childPath, component: pages[filePath] }]
        })
      }
    } else {
      // 没有布局,直接当普通路由
      routes.push({ path: routePath, component: pages[filePath] })
    }
  }
  // 额外处理:路由优先级(普通路由放动态路由前面,避免匹配歧义)
  routes.sort((a, b) => {
    const aIsDynamic = a.path.includes(':')
    const bIsDynamic = b.path.includes(':')
    if (aIsDynamic && !bIsDynamic) return 1
    if (!aIsDynamic && bIsDynamic) return -1
    return 0
  })
  return routes
}

(二)路由守卫怎么处理?

自动路由生成后,路由守卫和手动配置时一样用:

  • 全局守卫:直接在 router 实例上挂 beforeEach 等钩子。

    router.beforeEach((to, from, next) => {
      // 权限判断、埋点等逻辑
      next()
    })
  • 组件内守卫:在页面组件里写 beforeRouteEnter 等钩子,和手动配置路由完全一致。

自动路由的潜在问题与解决方案

自动路由虽香,但也有“暗坑”,提前避坑能少掉头发:

  1. 路径冲突/歧义
    多个文件生成相同 path 会导致路由混乱。解决方案:严格约定命名规则(比如动态路由必须用 [id] 包裹),再写个“重复路径检测函数”,生成路由后检查,有重复就抛错提醒。

  2. 动态路由参数获取
    自动生成的动态路由(如 /user/:id),页面里获取参数和手动配置一样,用 useRoute()

    import { useRoute } from 'vue-router'
    const route = useRoute()
    const id = route.params.id
  3. 路由匹配优先级
    pages/user.vuepages/user/[id].vue 同时存在,/user 会被 user/:id 错误匹配。解决方案:生成路由后,给 routes 排序——把“非动态路由”(没有 的)放“动态路由”前面(参考前面 sort 代码)。

自动路由在实际项目的应用场景

自动路由不是花里胡哨的玩具,而是能实实在在提效的工具,这些场景特别适合:

  1. 中大型后台管理系统
    页面多、模块多(订单、用户、商品…),自动路由让“文件路径=路由”,新增页面只需丢文件,不用改路由配置,团队协作更丝滑。

  2. 多页面营销站(企业官网)
    首页、关于我们、产品、案例…文件结构简单,自动路由能快速搭好路由系统,后期加“产品详情页”只需按路径放文件。

  3. 组件库文档站
    组件文档按组件名分目录(如 pages/components/button.md.vue),自动路由能让每个组件文档页对应 /components/button,维护起来超方便。

和 Nuxt.js 自动路由的区别

Nuxt.js 是 Vue 生态的服务端渲染框架,内置的自动路由更强大(支持嵌套、动态路由、布局、中间件等),还结合了 SSR、静态生成。

而普通 Vue 项目里的 auto-routes 是轻量化自定义方案——核心思路和 Nuxt 一致,但布局、中间件等进阶功能得自己写,如果项目需要 SSR/静态生成,直接用 Nuxt 更高效;如果是纯 SPA 项目,自己实现 auto-routes 更灵活,不用背 Nuxt 的额外复杂度。

vue-router auto-routes 本质是“约定式路由 + 自动扫描生成配置”,核心价值是“提效 + 降错”,不管用 Vite 还是 Webpack,只要掌握“文件扫描 → 路径解析 → 路由生成”的逻辑,再结合项目需求处理嵌套、布局等细节,就能搭出适合自己项目的自动路由系统,实际开发中,再注意命名规范、路由优先级这些细节,自动路由就能稳定又高效地跑起来~

(文章字数已超 1428 字,把自动路由从概念到实现、进阶、避坑全拆透,希望能帮你彻底搞懂这套提效方案~)

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门