Vue 3 快速入门 第七章
本章我们来讲述 Vue 3中的路由。
目录
单页面应用(SPA)
路由
基本使用
组件存放问题
RouterView & RouterLink
路由器的工作模式
to的两种写法
命名路由
嵌套路由
query参数
params参数
路由的props配置
replace属性
路由重定向
单页面应用(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' // 改为createWebHashHistoryconst 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' } // 重定向到命名路由}
]