vue3学习笔记之router(router4 + ts)
vue3学习笔记之router(router4 + ts)
一、背景与问题
在构建现代单页应用(SPA)时,路由系统是核心基础设施之一。Vue3引入了全新的响应式系统,而Vue Router 4作为官方推荐的路由解决方案,其设计需要与Vue3的Composition API深度集成。
传统单页应用面临三大挑战:
- 路由状态管理的复杂性
- 动态路由参数的类型安全
- 路由导航的性能优化
Vue Router 4通过以下创新解决了这些挑战:
- 基于Vue3的响应式系统重构
- 强类型支持(TypeScript集成)
- 面向对象的路由配置
- 更细粒度的导航控制
二、基本原理
1. 路由核心机制
Vue Router 4采用基于观察的路由匹配机制,其核心流程如下:
graph TD
A[用户输入URL] --> B{路由匹配}
B -->|匹配成功| C[触发路由组件]
B -->|匹配失败| D[404处理]
C --> E[组件更新]
D --> F[404组件]关键组件包括:
createRouter:创建路由实例createWebHistory:历史模式导航RouteRecordRaw:路由配置类型RouteLocation:当前路由信息NavigationFailure:导航失败事件
2. 响应式系统集成
Vue3的响应式系统通过ref和reactive实现状态同步,Vue Router 4通过以下方式深度集成:
const count = ref(0)
watch(() => count.value, (newVal) => {
console.log(`Count changed to ${newVal}`)
})在路由系统中,URL变化会触发响应式更新,确保组件能及时响应路由变化。
三、环境准备
创建项目结构:
my-project/
├── src/
│ ├── App.vue
│ ├── main.ts
│ ├── router/
│ │ └── index.ts
│ └── views/
│ ├── Home.vue
│ └── About.vue
├── tsconfig.json
└── package.json安装依赖:
npm install vue@3 vue-router@4 typescript @types/vue-routerTypeScript配置示例:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./dist",
"rootDir": "./src",
"types": ["node", "vue"]
}
}四、核心实现
1. 路由实例创建
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router关键点:
createWebHistory用于历史模式导航RouteRecordRaw类型确保类型安全- 路由配置数组的结构必须严格符合类型
2. 嵌套路由配置
const routes: Array<RouteRecordRaw> = [
{
path: '/user',
name: 'User',
component: () => import('../views/User.vue'),
children: [
{
path: 'profile',
name: 'Profile',
component: () => import('../views/Profile.vue')
},
{
path: 'posts',
name: 'Posts',
component: () => import('../views/Posts.vue')
}
]
}
]3. 动态路由参数
const routes: Array<RouteRecordRaw> = [
{
path: '/user/:id',
name: 'User',
component: () => import('../views/User.vue')
}
]在组件中获取参数:
export default defineComponent({
props: {
id: {
type: String,
required: true
}
},
setup(props) {
console.log('User ID:', props.id)
}
})五、完整案例
创建一个待办事项管理应用,包含首页和详情页:
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home.vue'
import TaskDetail from '../views/TaskDetail.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/task/:id',
name: 'TaskDetail',
component: TaskDetail,
props: true
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router<!-- src/views/Home.vue -->
<template>
<div>
<h1>待办事项</h1>
<ul>
<li v-for="task in tasks" :key="task.id">
<router-link :to="`/task/${task.id}`">{{ task.title }}</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
tasks: [
{ id: '1', title: '完成文档' },
{ id: '2', title: '修复BUG' },
{ id: '3', title: '部署服务器' }
]
}
}
}
</script><!-- src/views/TaskDetail.vue -->
<template>
<div>
<h1>任务详情</h1>
<p>任务ID: {{ id }}</p>
<p>任务标题: {{ title }}</p>
</div>
</template>
<script>
export default {
props: {
id: {
type: String,
required: true
},
title: {
type: String,
required: true
}
}
}
</script>// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')六、源码解析
1. 路由实例创建过程
const router = createRouter({
history: createWebHistory(),
routes
})内部会创建一个Router实例,其核心属性包括:
history: 历史记录管理器matcher: 路由匹配器options: 路由配置选项
2. 路由匹配机制
Vue Router 4通过createMatcher函数创建路由匹配器,其核心逻辑如下:
function createMatcher(routes, { ... }) {
const map = new Map()
const keys = []
for (const route of routes) {
if (route.name) {
map.set(route.name, route)
keys.push(route.name)
}
}
return {
match: (location) => {
for (const key of keys) {
const route = map.get(key)
if (matchRoute(location, route)) {
return route
}
}
return null
}
}
}七、进阶使用
1. 响应式路由参数
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/user/:id',
name: 'User',
component: User
}
]
})
watch(() => router.currentRoute.value, (to) => {
if (to.params.id) {
console.log('当前用户ID:', to.params.id)
}
})2. 导航守卫
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login')
} else {
next()
}
})3. 动态路由加载
const routes: Array<RouteRecordRaw> = [
{
path: '/dynamic',
name: 'Dynamic',
component: () => import('../views/Dynamic.vue')
}
]八、性能与工程实践
1. 路由懒加载优化
{
path: '/heavy',
name: 'Heavy',
component: () => import('../views/Heavy.vue') // 懒加载
}2. 组件缓存策略
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>3. 路由预加载
const routes: Array<RouteRecordRaw> = [
{
path: '/preloaded',
name: 'Preloaded',
component: () => import('../views/Preloaded.vue')
}
]九、常见问题与踩坑
1. 路由参数类型错误
错误示例:
{
path: '/user/:id',
name: 'User',
component: User
}改进方案:
{
path: '/user/:id',
name: 'User',
component: User,
props: (route) => ({ id: route.params.id })
}2. 历史模式服务器配置
错误场景:直接运行npm run serve时可能出现404
解决方法:
- 服务器配置:
nginx配置location / { try_files $uri $uri/ /index.html } - 本地开发:使用
vite的--history-api-fallback选项
3. 动态路由参数未绑定
错误示例:
<template>
<p>当前ID: {{ id }}</p>
</template>改进方案:
<script>
export default {
props: {
id: {
type: String,
required: true
}
}
}
</script>十、最佳实践
- 类型安全优先:始终使用
RouteRecordRaw类型定义路由配置 - 动态路由策略:对于需要参数的路由,使用
props: true或自定义props函数 - 导航守卫合理使用:避免过度使用
beforeEach,优先使用组件内onBeforeRouteUpdate - 性能优化:对于大项目,使用
import()进行路由懒加载 - 安全考虑:敏感参数使用
params而非query,避免暴露在URL中
十一、总结
Vue Router 4与Vue3的深度集成,为现代SPA开发提供了强大的支持。通过TypeScript的强类型支持,开发者可以更安全地管理路由配置和参数。在实际项目中,应根据需求选择合适的路由模式(hash/history),合理使用导航守卫和组件缓存策略。对于大型项目,建议采用模块化路由配置,结合懒加载和预加载技术优化性能。同时,要特别注意安全风险,避免敏感信息通过URL暴露。通过合理的设计和实践,Vue Router 4能够有效支撑复杂度不断增长的单页应用需求。
评论已关闭