项目配置信息如下
"vue": "^3.5.12",
"typescript": "~5.6.0",
"vite": "^5.4.10",
正文
在项目中,当路由组件变多时,手动去注册路由信息太过繁琐,在使用 Nuxt3 框架时发现该框架可以实现自动注册路由信息
于是找到源码参考了一下,发现可以通过 vite 的api import.mate.glob(string,object)拿到指定目录下所有的文件
那么,开始吧
在 src / router 目录下创建 auto-router.ts 文件,然后将目标拆解成一个个的需求并逐一解决
需求
-
匹配到指定目录的 .vue 文件
// 基础 import.meta.glob(globPattern, options) - globPattern:必填项,string 或 string[]。!!!注意:只能接收静态字符串,所以这里必须写死 - options:配置对象 - eager:布尔值,默认false。为true时,直接同步导入模块;若为false。返回异步函数,也就是懒加载效果 - exclude:string[],排除匹配的文件。 // 示例 const files = import.meta.glob('../pages/**/*.vue') console.log(files, "@files") { ../pages/Demo.vue : () => import("/src/pages/Demo.vue") } -
将匹配到的文件转化成可用路径
// 基础 let routePath = path .replace('../pages', '') .replace(/\.vue$/, '') // 匹配多级目录 .replace(/\[([^\]]+)\]/g, ':$1') // 匹配动态路由地址 .replace(/_/g, ':') // 允许传递参数,非必填 .replace(/\/:/g, '/:') // 修正路径格式 // 示例 pages/User/my.vue ===> http://localhost:5174/user/my pages/User/about/name.vue ===> http://localhost:5174/user/about/name pages/User/[id].vue ===> http://localhost:5174/user/:123456 || http://localhost:5174/user/:id=999&title=888 pages/User/user_id.vue ===> http://localhost:5174/user/user:123456 || http://localhost:5174/user/user:id=123456&title=888 -
将index自动转换成根目录
// 示例:这里自动转换成小写,也就意味着可以创建 Index.vue if (routePath.toLowerCase() === '/index') { routePath = '' } -
配置路由信息
// 示例 const route = { path: routePath === '' ? '/' : routePath, component: pages[path], name: routePath.replace(/\//g, '') || 'home', props: true // 启用props接收路由参数 } routes.push(route) // 保存配置好的路由信息 // 注意 vue-router 可以并推荐处理懒加载组件,所以不需要额外配置为异步组件 pages[path]: ===> () => import("/src/pages/About.vue") -
收尾工作
- 为了实现动态更新,需要把这些全放到一个方法中,该方法返回配置好的路由信息数组
// 确保静态路由优先于动态路由 routes.sort((a, b) => { const aDynamic = a.path.includes(':') const bDynamic = b.path.includes(':') if (aDynamic && !bDynamic) return 1 if (!aDynamic && bDynamic) return -1 return a.path.split('/').length - b.path.split('/').length }) // 添加未匹配路径重定向(如果配置了redirectNotFoundTo,通过参数传递) if (redirectNotFoundTo) { routes.push({ path: '/:pathMatch(.*)*', redirect: redirectNotFoundTo }) } return routes
代码
添加了类型检查的版本,如果不需要可以关闭 ts 的严格模式或使用 js
scr / auto-router.ts
import type { Component } from "vue";
import type { RouteRecordRaw } from 'vue-router'
/**
* 自动生成路由配置
*/
export const generateAutoRoutes = (redirectNotFoundTo: string = '/'): RouteRecordRaw[] => {
const pages: Record<string, () => Promise<Component>> = import.meta.glob('../pages/**/*.vue', { eager: false })
const routes: RouteRecordRaw[] = []
for (const path in pages) {
let routePath = path
.replace('../pages', '')
.replace(/\.vue$/, '')
.replace(/\[([^\]]+)\]/g, ':$1')
.replace(/_/g, ':')
.replace(/\/:/g, '/:')
if (routePath.toLowerCase() === '/index') {
routePath = ''
}
const route: RouteRecordRaw = {
path: routePath === '' ? '/' : `${routePath}`,
component: pages[path],
name: routePath.replace(/\//g, '') || 'home',
props: true
}
routes.push(route)
}
routes.sort((a, b) => {
const aDynamic = a.path.includes(':')
const bDynamic = b.path.includes(':')
if (aDynamic && !bDynamic) return 1
if (!aDynamic && bDynamic) return -1
return a.path.split('/').length - b.path.split('/').length
})
if (redirectNotFoundTo) {
routes.push({
path: '/:pathMatch(.*)*',
redirect: redirectNotFoundTo
})
}
return routes
}
src / index.ts
import { createRouter, createWebHistory } from "vue-router";
import { generateAutoRoutes } from "./auto-router"
const router = createRouter({
history: createWebHistory(),
routes: generateAutoRoutes()
});
export default router;
2476

被折叠的 条评论
为什么被折叠?



