本章我们来讲述 Vue 3中的路由。
目录
单页面应用(SPA)
所有功能在一个html页面上实现
举例:网易云音乐的官方网站 是一个典型的单页面应用(SPA,Single Page Application)。
而像百度、淘宝、京东这样的网站则是多页面应用。
以下是单页面应用(SPA)和多页面应用(MPA)的对比表格:
对比项 | 单页面应用(SPA) | 多页面应用(MPA) |
---|---|---|
定义 | 整个应用只有一个HTML页面,内容动态加载和更新 | 由多个独立HTML页面组成,页面跳转需重新加载 |
页面加载方式 | 仅首次加载完整页面,后续通过AJAX动态替换内容 | 每次页面跳转都需重新加载整个页面 |
用户体验 | 更流畅,接近原生应用的体验 | 页面切换时有明显刷新感 |
SEO友好性 | 较差,需额外优化(如SSR) | 天然友好,每个页面有独立内容和元信息 |
开发复杂度 | 较高(需前端路由、状态管理等) | 较低(传统开发模式) |
技术栈 | 常用React、Vue、Angular等框架 | 可使用任意技术(如纯HTML、jQuery等) |
服务器压力 | 首屏后服务器压力小(数据通过API交互) | 服务器压力较大(需频繁生成完整页面) |
首屏加载时间 | 可能较长(需加载框架和依赖) | 首屏较快(但后续页面需重复加载资源) |
路由管理 | 前端路由(如React Router、Vue Router) | 后端路由或天然页面路径 |
适用场景 | 高交互性应用(如Web应用、后台管理系统) | 内容型网站(如博客、电商、新闻站) |
代码维护 | 组件化开发,易于维护和复用 | 多页面重复代码可能较多 |
浏览器历史管理 | 需手动处理(通过History API) | 天然支持 |
数据共享 | 全局状态管理方便(如Vuex、Redux) | 依赖URL参数、Cookie或本地存储 |
单页面应用的使用场景:系统类网站、内部网站、文档类网站、移动端站点等
多页面应用的使用场景:公司官网、电商类网站等
路由
路径和组件的映射关系
基本使用
1.首先需要安装 Vue Router:
npm install vue-router@4
2.然后在src中新建router文件夹,然后再在文件夹里面新建index.ts(如果你使用的语言是js可以改成index.js)
3.在main.ts配置
import router from './router'
const app = createApp(App)
app.use(router)
4.配置index.ts
import { createRouter, createWebHistory } from 'vue-router'
import 组件对象 from '组件路径'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path:'路径', //如果为 / 表示默认路由
component: 组件对象,
},
],
})
export default router
当然如果你创建项目的时候选择了单页面应用的话上面的可以忽略,脚手架会自动为你创造文件,当然了路径和组件肯定是需要你自己设置
组件存放问题
为了便于维护我们会对组件进行分类
src/views 文件夹
页面组件-页面展示-配合路由使用
src/components 文件夹
服用组件-展示数据-常用于复用
RouterView & RouterLink
RouterView:
是一个功能组件,用于渲染匹配到的路由组件。
<template>
<div>
<RouterView></RouterView>
</div>
</template>
<script setup lang="ts">
import { RouterView } from 'vue-router';
</script>
RouterView用来展示组件
RouterLink:
用于创建导航链接,而不是使用常规的 <a> 标签。
<template>
<!-- active-class表示激活时的类名 -->
<RouterLink to="/home" active-class="home">Home</RouterLink>
</template>
路由器的工作模式
路由器一共有两种工作模式:HTML5 模式 (History 模式)、Hash模式
Hash模式
特点:
- 使用 URL 的 hash(#)来模拟完整 URL
- URL 格式如:http://example.com/#/path
- 不需要服务器端特殊配置
- 兼容性最好,支持所有浏览器
- 不会触发页面刷新
HTML5 模式 (History 模式)
特点:
- 使用 HTML5 History API
- URL 格式如:http://example.com/path
- 更美观的 URL,没有 #
- 需要服务器端配置支持(所有路由都指向 index.html)
- 不支持旧版本浏览器(IE9 及以下)
举例:网易云采用的就是Hash模式、而B站采用History 模式
对比:Hash vs History
特性 | Hash 模式 | History 模式 |
---|---|---|
URL 美观度 | 带 # (如 /#/path ) |
无 # (如 /path ) |
服务器要求 | 无需特殊配置 | 需配置 SPA 回退 |
兼容性 | 支持所有浏览器 | 依赖 HTML5 History API(IE10+) |
SEO | 较差(早期爬虫不解析 # ) |
较好(但需 SSR 配合) |
History模式服务器需要配置否则会404
// history 模式
import { createRouter, createWebHistory } from 'vue-router'
// 使用 createWebHistory 创建 History 模式的路由
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
// ...你的路由配置
]
})
export default router
// Hash 模式
import { createRouter, createWebHashHistory } from 'vue-router' // 改为createWebHashHistory
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL), // 使用 Hash 模式
routes: [
// ...你的路由配置
]
})
export default router
to的两种写法
<RouterLink active-class="home" to="/home">首页</RouterLink>
<RouterLink active-class="home" :to="{path:'/home'}">首页</RouterLink>
命名路由
当创建一个路由时,我们可以选择给路由一个name:
{
name:'home'
path: '/home',
component: HomePage,
},
然后我们可以使用 name 而不是 path 来传递 to 属性给<RouterLink>:
<RouterLink :to="{name:'home'}"></RouterLink>
嵌套路由
{
path: '/home',
component: HomePage,
children:[
{
path:'', // 默认路由
component: MainContent,
},
{
path:'other',
component: OtherContent,
},
]
}
<router-link to="/home/other">其他</router-link>
query参数
传参:
<RouterLink
:to="{
path:news,
query:{
id:news.id,
title:news.title,
content:news.content
}
}"
>
我们假设news,id是1,news,title是“标题”,news.content是"内容",那么跳转后的url就变成了
/news?id=1&title=标题&content=内容
获取数据:
import { useRoute } from 'vue-router';
const route = useRoute()
const query = route.query
params参数
首先要配置路由:
{
name: 'other',
path: '/other/:id/:title/:content',
component: OtherPage,
}
<RouterLink :to="{
name: '/other',
params: {
id: 1,
title: '标题',
content: '内容'
}
}">其他</RouterLink>
<template>
<div>
<h1>other</h1>
<p>标题:{{ params.title }}</p>
<p>内容:{{ params.content }}</p>
</div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router';
const route = useRoute()
const params = route.params
</script>
跳转后url变成/news/1/标题/内容
特性 | params |
query |
---|---|---|
显示位置 | 路径部分 (/user/123 ) |
URL查询参数 (/user?id=123 ) |
路由配置 | 需要定义动态段 (/user/:id ) |
不需要特殊配置 |
刷新后 | 保持(如果配置了动态路由) | 保持 |
适用场景 | 必需参数、简洁URL | 可选参数、筛选条件 |
与path |
不兼容 | 兼容 |
与name |
兼容 | 兼容 |
路由的props配置
{
name: 'other',
path: '/other/:id/:title/:content', // 将params参数作为 prop 传递给组件
component: OtherPage,
props: true
}
<template>
<div>
<h1>other</h1>
<p>标题:{{ title }}</p>
<p>内容:{{ content }}</p>
</div>
</template>
<script setup lang="ts">
defineProps(['id', 'title', 'content'])
</script>
props配置有三种写法:
1.布尔模式
也就是我们之前的props:true 只能处理params参数,且是传全部params参数
2.函数模式
props: (route) => ({
route.query
})
query参数我们也可以传,我们也可以自定义要传的参数如route.query.title
3.对象模式
对象模式是传递静态 props 给路由组件的一种简单方式。
props: {
id:1,
title:'标题',
content:'内容'
}
特性 | 布尔模式 | 对象模式 | 函数模式 |
---|---|---|---|
基本语法 | props: true |
props: { key: value } |
props: (route) => ({...}) |
适用场景 | 简单映射路由 params 到 props | 传递静态不变的 props | 需要动态计算或处理路由信息时 |
访问路由参数 | 自动映射 params 到同名 props | 无法访问路由参数 | 可通过 route 参数访问所有路由信息 |
类型转换 | 无自动转换(保持字符串类型) | 直接使用定义的值 | 可在函数内手动转换类型 |
灵活性 | 低(仅自动映射) | 中(固定值) | 高(完全自定义) |
组合能力 | 只能映射 params | 可组合多个静态值 | 可组合 params、query、静态值等 |
示例 | props: true |
props: { theme: 'dark' } |
props: (route) => ({ id: parseInt(route.params.id) }) |
与动态路由配合 | 完全匹配 params | 无法响应动态变化 | 完全响应动态变化 |
性能 | 最高(直接映射) | 高(静态值) | 较低(每次变化需执行函数) |
组件定义要求 | 组件 props 需与 params 同名 | 组件 props 需与对象键名匹配 | 无特殊要求 |
replace属性
replace 是 Vue Router 中用于控制导航行为的一个属性,它决定了导航时是否替换当前的历史记录条目而不是添加新的条目。
基本作用
默认行为(不使用 replace):添加新的历史记录条目(相当于 history.pushState())
使用 replace: true:替换当前历史记录条目(相当于 history.replaceState())
声明式导航
<router-link to="/home" replace>首页</router-link>
编程式导航(里面的内容:to怎么写它怎么写)
// 替换当前历史记录而不是添加新记录
router.push({ path: '/home', replace: true })
// 或简写方式
router.replace('/home')
路由重定向
允许你将一个 URL 自动转向另一个 URL
[
{
path: '/home',
redirect: '/dashboard' // 简单重定向
},
{
path: '/old-article/:id',
redirect: '/new-article/:id' // 保持动态参数的重定向
},
{
path: '/legacy-path',
redirect: { name: 'newRoute' } // 重定向到命名路由
}
]