不少刚开始用Vue Router搭配TypeScript开发的同学,总会碰到「RouteRecordRaw」这个词,它到底是干啥的?写路由配置时怎么正确用它?今天咱们就把这些疑问掰碎了聊清楚~
RouteRecordRaw到底是什么?
简单说,RouteRecordRaw是Vue Router里用来描述「路由记录原始结构」的类型(TypeScript环境下),路由系统要把我们写的路由配置,转换成能识别的规则去匹配URL、渲染组件,RouteRecordRaw就是给这份「原始配置」定规矩的——规定每个路由项得有哪些字段、每个字段是什么格式。
举个例子,你写一个路由对象 { path: '/home', name: 'Home', component: HomeView }
,它的类型就是RouteRecordRaw,要是用TypeScript,定义路由数组时写 const routes: RouteRecordRaw[] = []
,TypeScript就会帮你检查每个路由项:path格式对不对?name是不是字符串?component有没有正确引入?避免你把component
写成components
、path写成paths
这类低级错误。
不用RouteRecordRaw会怎样?
如果不用这个类型约束,相当于给路由配置“裸奔”,比如你不小心把component
写成components
,VSCode不会报红提醒,直到运行项目时才发现页面不渲染、路由跳转失效,这时候debug要花很多时间找哪里写错了。
而用了RouteRecordRaw,写代码时TypeScript就像个“实时检查员”,一旦字段名、格式不对,立刻标红提醒,相当于把很多运行时才会暴露的错误,提前到编码阶段解决,能省不少调试精力。
怎么用RouteRecordRaw写路由配置?
下面分几种常见路由场景,看看具体怎么配:
(1)基础静态路由
最基础的路由长这样:
import { RouteRecordRaw } from 'vue-router' import HomeView from '../views/HomeView.vue' const routes: RouteRecordRaw[] = [ { path: '/', name: 'home', component: HomeView } ]
这里要注意3个核心字段:path(路由路径)、name(路由命名,可选但建议写,方便编程式导航)、component(对应的页面组件),RouteRecordRaw会检查这几个字段的类型和格式,比如path必须是字符串,component必须是组件或异步加载函数。
(2)动态路由(带参数)
如果要做用户详情页,需要通过/user/123
这种路径传ID,路由配置得这么写:
const routes: RouteRecordRaw[] = [ { path: '/user/:id', // 动态段用:id表示 name: 'user', component: () => import('../views/UserView.vue') // 也可以用懒加载 } ]
RouteRecordRaw对path的动态参数格式有约束,必须用:参数名
的形式,要是你写成/user_id/:id
(多了下划线),TypeScript会提示“类型不匹配”,提前拦掉这种格式错误。
(3)嵌套路由(children)
比如有个Dashboard布局页,里面要嵌套Overview、Analysis等子页面,路由得嵌套着写:
const routes: RouteRecordRaw[] = [ { path: '/dashboard', component: () => import('../views/DashboardLayout.vue'), children: [ { path: 'overview', // 注意:子路由path不用加/,是相对父路由的路径 component: () => import('../views/OverviewView.vue') }, { path: 'analysis', component: () => import('../views/AnalysisView.vue') } ] } ]
这里children本身也是RouteRecordRaw的数组,所以每个子路由项也要符合结构要求,而且子路由的path是相对父路由的,比如父路由是/dashboard
,子路由写overview
,最终匹配的是/dashboard/overview
,要是你给子路由path加了(写成/overview
),就会变成绝对路径,导致匹配错误,这时候RouteRecordRaw不会拦(因为格式没毛病),但逻辑会错,得自己注意。
(4)重定向(redirect)和别名(alias)
如果要把旧路径重定向到新路径,或者给路径起别名,配置长这样:
const routes: RouteRecordRaw[] = [ { path: '/old-path', redirect: '/new-path' // 重定向 }, { path: '/main', alias: '/index' // 别名,访问/index也能打开/main的页面 } ]
RouteRecordRaw里内置了redirect和alias的类型定义,写的时候要注意字段名别拼错(比如把redirect写成redirct),否则TypeScript会立刻报错。
RouteRecordRaw和路由实例化有啥关系?
当我们用createRouter
创建路由实例时,需要传入routes配置:
import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes // 这里的routes必须是RouteRecordRaw[]类型 })
Router构造函数内部会把这些「原始路由记录」(RouteRecordRaw)转换成内部路由对象——处理path解析、组件加载逻辑(比如懒加载的import)、嵌套路由关系等,所以RouteRecordRaw是“原材料”,路由系统加工后变成能工作的“成品”,用来匹配URL、渲染组件。
结合懒加载时要注意啥?
很多项目为了优化首屏加载速度,会用路由懒加载,
component: () => import('../views/AboutView.vue')
RouteRecordRaw对这种异步加载函数的支持很好,类型上是兼容的,但要注意2个点:
- ① 导入路径别写错:比如少写.vue后缀(如果是Vue单文件组件),TypeScript可能不会报错(因为路径解析由Vite/Webpack这类构建工具处理),但运行时会报“找不到模块”,所以写懒加载时,路径要仔细核对,比如确认是
../views/AboutView.vue
而不是../view/AboutView.vue
(少了个s)。 - ② 动态导入的组件要存在:如果团队协作时,有人删了AboutView.vue文件,TypeScript也没法提前发现(因为是运行时加载),所以最好配合Git钩子、代码审查来避免这种情况。
能给RouteRecordRaw加自定义字段吗?
当然可以!比如我们想给路由加个title(页面标题)、requiresAuth(是否需要登录)这类自定义信息,通常放在meta里:
// 先扩展RouteMeta类型(Vue Router内置的meta类型) declare module 'vue-router' { interface RouteMeta {: string; requiresAuth?: boolean; } } const routes: RouteRecordRaw[] = [ { path: '/profile', component: () => import('../views/ProfileView.vue'), meta: { title: '个人中心', requiresAuth: true } } ]
如果想加meta以外的自定义字段,比如给每个路由加个customTag
,可以这样扩展RouteRecordRaw:
declare module 'vue-router' { interface RouteRecordRaw { customTag?: string; } } const routes: RouteRecordRaw[] = [ { path: '/special', component: SpecialView, customTag: 'vip' // 现在可以正常写自定义字段了 } ]
这样扩展后,TypeScript就允许RouteRecordRaw有customTag字段,既保持类型约束,又满足业务定制需求。
常见错误场景咋解决?
实际开发中,这些错误很常见,提前避坑能省很多事:
(1)字段名拼写错误
比如把component
写成components
,VSCode会立刻报红:“类型"{ path: string; name: string; components: ... }"不符合RouteRecordRaw的结构”,解决方法很简单——检查字段名,改成正确的component
。
(2)动态路由参数格式错
如果把/user/:id
写成/user_id/:id
(多了下划线),TypeScript会提示“类型字符串不符合路由路径规则”,这类错误属于格式问题,修正path的动态段写法就行,比如改成/user/:id
。
(3)懒加载路径错误
假设要加载AboutView.vue,却写成import('../views/AbotView.vue')
(拼写错),TypeScript可能不会报错(因为路径是字符串,TS没法判断文件是否存在),但运行时会404,解决方法是写完路径后,手动检查一遍,或者配合IDE的路径自动补全功能。
(4)嵌套路由path写绝对路径
父路由是/dashboard
,子路由写成path: '/overview'
,这会让子路由匹配/overview
而不是/dashboard/overview
,导致页面不显示,RouteRecordRaw不会拦这种逻辑错误,所以写嵌套路由时,子路由path别加/ ,保持相对路径。
实战:从0到1配个TS路由
假设现在要新建一个Vue 3 + TypeScript + Vue Router 4的项目,完整的路由配置流程是这样的:
步骤1:安装依赖
打开终端,执行:
npm install vue-router@4
步骤2:创建路由文件
在src
目录下新建router/index.ts
如下:
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' // 引入静态组件 import HomeView from '../views/HomeView.vue' const routes: RouteRecordRaw[] = [ // 基础路由 { path: '/', name: 'home', component: HomeView }, // 带命名的路由 { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') // 懒加载 }, // 动态路由 { path: '/user/:id', name: 'user', component: () => import('../views/UserView.vue') }, // 嵌套路由 { path: '/dashboard', component: () => import('../views/DashboardLayout.vue'), children: [ { path: 'overview', component: () => import('../views/OverviewView.vue') }, { path: 'analysis', component: () => import('../views/AnalysisView.vue') } ] }, // 重定向 { path: '/old', redirect: '/new' }, // 带meta的路由 { path: '/profile', component: () => import('../views/ProfileView.vue'), meta: { title: '个人中心', requiresAuth: true } } ] const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes }) export default router
步骤3:在main.ts里挂载路由
import { createApp } from 'vue' import App from './App.vue' import router from './router' const app = createApp(App) app.use(router) app.mount('#app')
这样一套配置下来,每个路由项都被RouteRecordRaw约束着,TypeScript会帮你检查大部分错误,比如要是把component
写成components
,VSCode会立刻标红,提醒你字段错误。
RouteRecordRaw是路由的“安全网”
对Vue Router+TypeScript项目来说,RouteRecordRaw不是额外的负担,而是保证路由配置规范、减少错误的重要工具,它像个“安全网”,在你写路由时提前拦住字段拼写、格式这类低级错误,让路由系统更稳定。
刚开始接触可能觉得类型约束有点麻烦,但熟悉后会发现——它帮你省的调试时间,远比写类型的那点功夫多,尤其是团队协作时,统一用RouteRecordRaw约束路由配置,能减少很多“为什么我这路由不生效”的沟通成本~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。