一、路由基础概念
1.1 路由的本质
路由在前端开发中扮演着至关重要的角色,它的核心本质是URL与UI组件之间的映射关系管理。从传统的多页面应用到现代单页面应用,路由的演进体现了Web开发理念的重大转变。
传统路由 vs 前端路由:
-
传统路由:每次URL变化都向服务器请求新页面,导致完整页面刷新
-
前端路由:URL变化只在客户端处理,通过JavaScript动态更新页面内容
1.2 SPA架构
单页面应用(SPA)不是简单的"一个HTML文件",而是一种应用架构模式:
TypeScript
// SPA核心特征示例
interface SPATraits {
singleEntry: boolean; // 单一入口
clientSideRendering: boolean; // 客户端渲染
dynamicUpdates: boolean; // 动态更新
ajaxDataFetching: boolean; // AJAX数据获取
}
SPA的优势:
-
用户体验:接近原生应用的流畅度,无刷新跳转
-
开发效率:前后端分离,并行开发
-
性能优化:资源按需加载,减少服务器压力
SPA的挑战与解决方案:
-
SEO问题:通过SSR(服务端渲染)或预渲染解决
-
首屏加载:代码分割、懒加载优化
-
状态管理:Vuex/Pinia等状态管理库
二、Vue Router安装与配置
2.1 环境准备与最佳实践
bash
# 推荐使用Vue CLI或Vite创建项目
npm create vue@latest my-project
cd my-project
npm install vue-router@4
2.2 路由配置的完整架构
TypeScript
// src/router/index.ts - 完整配置示例
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
// 定义路由元信息类型,增强类型安全
declare module 'vue-router' {
interface RouteMeta {
requiresAuth: boolean;
title: string;
breadcrumb?: string[];
}
}
// 路由配置数组
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: {
requiresAuth: false,
title: '首页'
}
},
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue'),
meta: {
requiresAuth: false,
title: '关于我们'
}
}
];
// 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
// 滚动行为控制
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
return { top: 0 };
}
}
});
export default router;
2.3 路由注册与应用初始化
TypeScript
// src/main.ts - 完整注册流程
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
// 注册路由
app.use(router);
// 全局路由错误处理
router.onError((error) => {
console.error('路由错误:', error);
});
app.mount('#app');
三、路由模式对比
3.1 History模式
实现原理:
-
基于HTML5 History API(pushState, replaceState)
-
需要服务器配置支持
示例:
TypeScript
const router = createRouter({
history: createWebHistory(), //history模式
/******/
});
3.2 Hash模式适用场景
技术特点:
-
使用URL hash(#)管理路由
-
兼容性极佳,支持IE9+
适用场景:
-
静态网站部署
-
无服务器配置权限
-
对SEO要求不高的内部系统
示例:
TypeScript
const router = createRouter({
history: createWebHashHistory(), //hash模式
/******/
});
|---------|----------------------------|------------------------------------|
| | 优点 | 缺点 |
| History | URL 更加美观,不带有#,更接近传统的网站 URL | 后期项目上线,需要服务端配合处理路径问题,否则刷新会有 404 错误 |
| Hash | 兼容性更好,因为不需要服务器端处理路径 | URL 带有#不太美观,且在 SEO 优化方面相对较差 |
四、路由导航全面
4.1 声明式导航高级用法
TypeScript
<!-- 第一种:to的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link>
<!-- 第二种:to的对象写法 -->
<router-link active-class="active" :to="{ path: '/home' }">Home</router-link>
TypeScript
<template>
<nav class="main-navigation">
<!-- 基础导航 -->
<RouterLink
to="/home"
active-class="active-link"
exact-active-class="exact-active-link"
class="nav-item"
>
首页
</RouterLink>
<!-- 对象语法 -->
<RouterLink
:to="{
name: 'userProfile',
params: { userId: 123 },
query: { tab: 'settings' }
}"
class="nav-item"
>
用户设置
</RouterLink>
<!-- 自定义渲染 -->
<RouterLink
to="/cart"
v-slot="{ href, route, navigate, isActive, isExactActive }"
custom
>
<a
:href="href"
@click="navigate"
:class="{
'nav-item': true,
'active': isActive,
'exact-active': isExactActive
}"
>
购物车
<span v-if="route.meta.cartCount" class="badge">
{{ route.meta.cartCount }}
</span>
</a>
</RouterLink>
</nav>
</template>
4.2 编程式导航完整指南
命名路由
可以简化路由跳转及传参
给路由规则命名
TypeScript
routes: [
{
name: "zhuye",
path: "/home",
component: Home,
},]
跳转路由
TypeScript
<!--简化前:需要写完整的路径(to的字符串写法) -->
<router-link to="/news/detail">跳转</router-link>
<!--简化后:直接通过名字跳转(to的对象写法配合name属性) -->
<router-link :to="{ name: 'guanyu' }">跳转</router-link>
TypeScript
// 组合式API写法
import { useRouter, useRoute } from 'vue-router';
export default {
setup() {
const router = useRouter();
const route = useRoute();
const navigationMethods = {
// 基础导航
goToHome() {
router.push('/home');
},
// 命名路由导航
goToUserProfile(userId: number) {
router.push({
name: 'userProfile',
params: { userId }
});
},
// 带查询参数
goToSearch(keyword: string) {
router.push({
path: '/search',
query: { q: keyword, page: 1 }
});
},
// 替换当前路由(不添加历史记录)
replaceCurrent() {
router.replace('/new-path');
},
// 前进后退
goForward() {
router.go(1);
},
goBack() {
router.back();
},
// 条件导航
conditionalNavigate() {
if (route.name !== 'target') {
router.push('/target');
}
}
};
return {
...navigationMethods
};
}
};
五、路由传参
5.1 Query参数
适用场景:
-
可选参数
-
筛选条件
-
分页信息
-
排序参数
TypeScript
<!-- 跳转并携带query参数(to的字符串写法) -->
<router-link to="/news/detail?a=1&b=2&content=欢迎你">
跳转
</router-link>
<!-- 跳转并携带query参数(to的对象写法) -->
<RouterLink
:to="{
//name:'xiang', //用name也可以跳转
path: '/news/detail',
query: {
id: news.id,
title: news.title,
content: news.content,
},
}"
>
{{news.title}}
</RouterLink>
<!--接收参数-->
import { useRoute } from "vue-router";
const route = useRoute();
// 打印query参数
console.log(route.query);
5.2 Params参数
路由配置:
TypeScript
{
path: '/user/:userId/profile/:tab?',
name: 'userProfile',
component: UserProfile,
props: true
}
参数传递与接收:
TypeScript
<template>
<!-- 传递params参数 -->
<RouterLink
:to="{
name: 'userProfile',
params: {
userId: 123,
tab: 'settings'
}
}"
>
用户设置
</RouterLink>
</template>
<script setup lang="ts">
// 接收params参数
import { defineProps } from 'vue';
interface Props {
userId: string;
tab?: string;
}
const props = defineProps<Props>();
</script>
备注: 1. 传递 params 参数时,若使用 to 的对象写法,必须使用 name 配置项,不能用 path
- 传递 params 参数时,需要提前在规则中占位
①to字符串写法+query/params实现传参:
to字符串写法+query传参:
传: router-link的 to="路由路径+?键名=键值&键名=键值"
接: 接收route()方法中的 query属性值
to字符串写法+params传参:
前提条件:在路由配置的path中添加 路由路径/:参数1/:参数2
传: router-link的 to="路由路径/参数1/参数2"
接: 接收route()方法中的 params属性值
②to对象型写法-
1 name+query/params实现传参:
to对象型写法name+query传参:
传: router-link的 to="{name:路由name,query:{k:v}}"
接: 接收route()方法中的 query属性值
to对象型写法name+params传参:
前提条件:在路由配置的path中添加 路由路径/:参数1/:参数2
传: router-link的 to="{name:路由name,params:{k:v}}"
接: 接收route()方法中的 params属性值
-2 path+query/params实现传参:
to对象型写法path+query传参:
传: router-link的 to="{path:路由name,query:{k:v}}"
接: 接收route()方法中的 query属性值
to对象型写法path+params传参:不能传递参数
5.3 Props配置的三种模式
作用让路由组件更方便的收到参数(可以将路由参数作为 props 传给组件)
TypeScript
// 路由配置
{
path: '/article/:id',
name: 'article',
component: Article,
// 模式1:布尔模式 - 将params转为props
// props: true,
// 模式2:对象模式 - 传递静态props
// props: { theme: 'dark', showAuthor: true },
// 模式3:函数模式 - 动态计算props
props: (route) => ({
id: Number(route.params.id),
query: route.query,
meta: route.meta
})
}
5.4replace 属性
作用控制路由跳转时操作浏览器历史记录的模式
浏览器历史记录写入方式
push:追加历史记录(默认值)
replace:替换当前记录
示例
TypeScript
<RouterLink replace .......>News</RouterLink>
5.5重定向
作用 将特定的路径,重新定向到已有路由
具体编码
TypeScript
{
path:'/',
redirect:'/about'
}
404页面
TypeScript
{
path: "/:pathMatch(.*)*",
name: "NotFound",
component: NotFound,
},
使用通配符 /:pathMatch(.) 匹配所有未定义的路径 对应 NotFound 组件