vue3 快速入门系列 —— vue3 路由
vue3 快速入门系列 - vue3 路由
在vue3 基础上加入路由。
vue3 需要使用 vue-router V4,相对于 v3,大部分的 Vue Router API 都没有变化。
Tip:不了解路由的同学可以看一下笔者之前的文章:vue2 路由
vue-router V4
在 Vue Router API 从 v3(Vue2)到 v4(Vue3)的重写过程中,大部分的 Vue Router API 都没有变化,但是在迁移你的程序时,你可能会遇到一些破坏性的变化 —— 从 Vue2 迁移
vue3 需要使用 vue-router 4.x.x 版本。安装:
PS hello_vue3> npm i vue-router
changed 37 packages, and audited 69 packages in 3s
8 packages are looking for funding
run `npm fund` for details
1 moderate severity vulnerability
To address all issues, run:
npm audit fix
Run `npm audit` for details.
版本:
"dependencies": {
"vue": "^3.4.15",
"vue-router": "^4.3.0"
},
第一个示例
在vue3项目中加入路由。
步骤如下:
- 创建路由
src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
// new Router 变成 createRouter
const router = createRouter({
// mode: 'history' 配置已经被一个更灵活的 history 配置所取代
// 必填。否则报错:Uncaught Error: Provide the "history" option when calling "createRouter()"
history: createWebHistory(),
routes
})
export default router
Tip:new Router 变成 createRouter 来创建路由;其中模式需要通过调用方法创建,必填。
- 创建两个组件
<template>
<div>
<h1>About</h1>
// 可以通过设置router-link-active类来为被选中的路由添加样式
<router-link to="/">to Home</router-link>
</div>
</template>
<template>
<div>
<h1>Home</h1>
<router-link to="/about">to About</router-link>
</div>
</template>
- App.vue 中引入
<router-view>告诉 Vue Router 在哪里渲染匹配到的组件。
<template>
<router-view></router-view>
</template>
<script lang="ts" setup name="App">
</script>
- main.ts 通过 use 使用路由
import {createApp} from 'vue'
import App from './App.vue'
// 会自动加载 ./router/index.ts
import router from './router'
createApp(App)
// 将 Vue Router 插件安装到 Vue 实例中,以便在整个应用程序中使用 Vue Router 的功能
// Vue.use(MyPlugin) - 调用 `MyPlugin.install(Vue)`
.use(router)
.mount('#app')
接着就可以通过浏览器体验:
Home
// 点击,调整到 about 路由
to About
About
// 点击,调整到 home 路由
to Home
Tip: 通过 .use(router) 在 vue 开发者工具中就会看到路由tab。

命名路由
Tip: vue2 路由 -> 命名路由
路径有时太麻烦,可以使用命名路由替代。
例如将 About 从路径改为名称跳转。核心代码如下:
// 定义 name
{ path: '/about', component: About, name: 'guanyu' },
// 跳转
:to="{name: 'guangyu'}"
Tip:to 目前有2种写法,感觉字符串方式很痛快,对象还需要写好多,但是到子路由或传递参数,会发现还是对象好用。
// 传递字符串 - 理解为目标路由的路径
to="/"
// 传递对象
:to="{path: '/'}"
:to="{name: 'guangyu'}"
嵌套路由
Tip:和 vue2 中路由用法相同,详情请看:vue2 路由 -> 嵌套路由
新建一个 Article 组件,里面定义一个 router-view。请看示例:
- Article.vue
<template>
<div>
<h1>Article</h1>
// path 需要将一级路由路径加上,例如 /article,不能只写 detail。该 name 也方便。
// query 效果:http://localhost:5173/article/detail?id=1
<router-link :to="{ path: '/article/detail', query: { id: 1 } }">文章 id1 详情</router-link><br>
<router-link :to="{ path: '/article/detail', query: { id: 2 } }">文章 id2 详情</router-link><br>
// 注:将对象换成字符串,效果相同
<router-link to="/article/detail?id=3">文章 id3 详情</router-link><br>
<router-view></router-view>
</div>
</template>
<script lang="ts" setup name="App">
// 可以不引入
// import {RouterView,RouterLink} from 'vue-router'
</script>
Tip:可以不引入 import {RouterView,RouterLink} from 'vue-router'
- Detail.vue
<template>
<div>
<h1>文章id: {{ $route.query.id }}</h1>
</div>
</template>
- 增加路由和子路由。子路由的 path 无需增加
/
const routes = [
{ path: '/home', component: Home,},
{
path: '/article',
component: Article,
children: [
{
path: 'detail',
component: Detail
}
]
},
]
- Home.vue 增加Article入口
<router-link :to="{name: 'guanyu'}">About</router-link>
<br>
<router-link :to="{path: '/article'}">Article</router-link>
测试:进入Home,点击 Article,点击 文章 id1 详情,显示 文章id: 1,测试通过。
路由 query 参数
在”嵌套路由“中我们是这样取得 query 参数:<h1>文章id: {{ $route.query.id }}</h1>
js 中通过 useRoute hooks 取得 $route。请看示例:
<template>
<div>
<h1>文章id: {{ $route.query.id }}</h1>
<h1>文章id: {{ query.id }}</h1>
</div>
</template>
<script lang="ts" setup name="App">
import {toRefs} from 'vue'
// 返回当前的路由地址。相当于在模板中使用 $route。
// useRouter 返回路由器实例。相当于在模板中使用 $router
import {useRoute} from 'vue-router'
const route = useRoute()
// route: Proxy
console.log('route: ', route);
// 错误:解构需要用到 toRefs,否则页面不会更新
// const {query} = route
// 正确:解构
const {query} = toRefs(route)
</script>
Tip:如果需要解构,需使用 toRefs。若想将 query.id 中的 query 去掉,可以使用后面章节的 路由 props 属性,代码将更优雅
路由 params 参数
Tip:请看 vue2 路由 -> $route.params
将上节 query 参数示例改成 params。
- params需要增加
占位符,比如:id
{
path: '/article',
component: Article,
children: [
{
name: 'xiangxi',
path: 'detail/:id',
component: Detail
}
]
},
- id传递方式调整一下,不用 query 那种方式:
<router-link to="/article/detail/4">文章 id4 详情</router-link><br>
- 接收 id
<h1>文章id: {{ $route.params.id }}</h1>
注:params 不能传数组或对象;/a/:b/:c,则你必须传 /a/1/2,如果传 /a/1 则报错,如果有时没有c 可传,可以改成 /a/:b/:c?
对象形式
将 to 改成对象形式:
<router-link :to="{
path: '/article/detail/4',
params: {
id: 5
}
}">文章 id5 详情</router-link><br>
浏览器报错更容易理解,说 path 被忽略:
// vscode 报错:
对象字面量只能指定已知属性,并且“params”不在类型“RouteLocationPathRaw”中。
// 浏览器报错
[Vue Router warn]: Path "/article/detail/4" was passed with params but they will be ignored. Use a named route alongside params instead.
将 path 改成 name即可:
<router-link :to="{
// path: '/article/detail/4',
name: 'xiangxi',
params: {
id: 5
}
}">文章 id5 详情</router-link><br>
路由 props 属性
不就是想接收 params 或 query 传来的参数的,还得写这么一大块代码,太麻烦:
<template>
<div>
<h1>文章id: {{ query.id }}</h1>
</div>
</template>
<script lang="ts" setup name="App">
import {toRefs} from 'vue'
import {useRoute} from 'vue-router'
const route = useRoute()
const {query} = toRefs(route)
</script>
可以通过 props 解决。细节如下:
props 布尔
- 定义 props
{
name: 'xiangxi',
path: 'detail/:id',
component: Detail,
// 通过 props 属性来将路由参数传递给组件
// 底层好些这样:<Detail id=5/>
props: true
}
- 直接通过 defineProps 接收
<template>
<div>
<h1>文章id: {{id }}</h1>
</div>
</template>
<script lang="ts" setup name="App">
defineProps(['id'])
</script>
props 函数
如果需要接收 query,需要用 props 函数,参数是 route,返回需要接收的对象:
// RouteLocationNormalized 是 Vue Router 中的一个类型,它用于描述路由的位置信息
import { type RouteLocationNormalized } from 'vue-router';
{
name: 'xiangxi',
path: 'detail',
component: Detail,
// 通过 props 属性来将路由参数传递给组件
// props: true
props(route: RouteLocationNormalized ) {
return route.query
}
}
- 触发路由从 params 改成 query:
<router-link :to="{
name: 'xiangxi',
query: {
id: 5
}
}">文章 id5 详情</router-link><br>
- 接收方式不变:
<template>
<div>
<h1>文章id: {{id }}</h1>
</div>
</template>
<script lang="ts" setup name="App">
defineProps(['id'])
</script>
Tip:其实 props: true 就相当于下面这段代码:
props(route: RouteLocationNormalized ) {
return route.params
}
props 对象
props 还可以写成对象,但用得较少:
props: {
id: 100
}
replace
HTML5的历史API包含了pushState(),replaceState()和popstate事件
路由默认是 push。比如启动第一个示例,未点击 home 或 about 导航时,浏览器左上方既不能前进也不能后退,因为栈中只有当前页面,指针没地方去。在你点击home和about导航后,就可以前进和后退,即使刷新页面,这个历史记录也不会变。
<router-link :to="{name: 'guanyu'}">About</router-link>
<br>
<router-link :to="{path: '/article'}">Article</router-link>
vue-router 的 replace 作用和用法和 react replace 相同。
现在点 About 就会直接替换
<router-link replace :to="{name: 'guanyu'}">About</router-link>
编程式导航
Tip:vue2 路由 -> 编程式导航
三秒后跳转到 article:
<script lang="ts" setup name="App">
import { useRouter } from 'vue-router'
const router = useRouter()
type Path = string
// 说vue2 中编程式导航重复跳转会报错,vue3中没这个问题
function to(path: Path){
router.push(path)
}
setTimeout(() => {
to('/article')
}, 3000)
</script>
编程式导航使用频率大于声明式导航(<router-link :to="...">)
to也支持对象,和声明式导航用法相同,更多介绍请看:vuer-router v4 编程式导航
其他
路由组件和一般组件
路由组件通常放在 pages 或 views 文件夹中,一般组件通常放在 components 文件夹中 —— 一般开源的项目都会这样分类
看一个组件是哪种,需要看其如何用。比如定义一个 Demo.vue,如果通过标签 <Demo/> 这种写法来使用,就属于一般组件,如果该组件通过路由渲染,则称为路由组件。
卸载和挂载
通过导航,视觉上消失的路由组件,默认被卸载,需要用的时候在挂载。
在 第一个示例 中给 About.vue 增加两个生命周期钩子,再次切换 Home 和 About 组件,就能看到效果:
<template>
<div>
<h1>About</h1>
<router-link to="/">Home</router-link>
</div>
</template>
<script lang="ts" setup name="App">
import {onMounted, onUnmounted} from 'vue'
onMounted(() => {
console.log('About 挂载了');
})
onUnmounted(() => {
console.log('About 卸载了');
})
</script>
路由模式
history 模式 url 美观,后期上线,需要服务端配合处理路径问题,否则刷新会有404。当用户在浏览器中直接访问一个路由,或者刷新页面时,如果服务器端没有正确配置,可能会导致 404 错误,因为此时服务器会尝试去寻找对应的文件或路由路径,而实际上这个路径是由前端控制的,并不一定存在于服务器端的文件系统中。为了解决这个问题,你需要在服务器端配置一个通配符路由,将所有的路由请求都指向你的应用的入口文件(比如 index.html),这样就会确保 Vue Router 能够正确地处理路由请求。
如果你使用的是 Node.js 服务器,可以使用 Express 框架来进行配置,示例代码如下所示:
const express = require('express');
const path = require('path');
const app = express();
// 静态资源目录,例如你的 CSS、JavaScript 文件等
app.use(express.static(path.join(__dirname, 'public')));
// 通配符路由,将所有的路由请求都指向 index.html
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
// 启动服务器,监听端口
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
这样配置后,无论用户访问哪个路由,服务器都会返回 index.html,然后 Vue Router 就可以根据路由配置来正确地渲染相应的组件,避免了刷新页面时出现的 404 错误。
Hash 模式在 SEO 优化方面相对较差。
- 比如
不利于搜索引擎爬虫:Hash 模式下,URL 中的哈希部分(#后面的内容)不会被包含在 HTTP 请求中,因此在服务器接收请求时,哈希部分对于服务器来说是不可见的。这意味着搜索引擎爬虫无法直接获取到 URL 中的实际内容,因为爬虫主要是通过 HTTP 请求获取页面内容的,所以无法获取到 hash 后面的内容,这样就会导致搜索引擎无法正确地索引和解析页面。
虽然使用 history 模式相对于 hash 模式在 SEO 优化方面有所改善,但它仍然是单页应用(SPA),可以和服务端渲染结合
没有匹配到指定的路径 /
配置如下路由,第一次打开,浏览器控制台有警告:main.ts:9 [Vue Router warn]: No match found for location with path "/"
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About, name: 'guanyu' }
]
可以通过重定向解决。就像这样:
const routes = [
{ path: '/', redirect: '/home'},
{ path: '/home', component: Home,},
vue3 快速入门系列 —— vue3 路由的更多相关文章
- 快速入门系列--MVC--02路由
现在补上URL路由的学习,至于蒋老师自建的MVC小引擎和相关案例就放在论文提交后再实践咯.通过ASP.NET的路由系统,可以完成请求URL与物理文件的分离,其优点是:灵活性.可读性.SEO优化.接下来 ...
- 快速入门系列--MVC--01概述
虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入.其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的 ...
- 快速入门系列--MVC--07与HTML5移动开发的结合
现在移动互联网的盛行,跨平台并兼容不同设备的HTML5越来越盛行,很多公司都在将自己过去的非HTML5网站应用渐进式的转化为HTML5应用,使得一套代码可以兼容不同的物理终端设备和浏览器,极大的提高了 ...
- vue 快速入门 系列 —— vue-cli 上
其他章节请看: vue 快速入门 系列 Vue CLI 4.x 上 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...
- 快速入门系列--WebAPI--01基础
ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因 ...
- 快速入门系列--WebAPI--03框架你值得拥有
接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...
- 快速入门系列--WebAPI--04在老版本MVC4下的调整
WebAPI是建立在MVC和WCF的基础上的,原来微软老是喜欢封装的很多,这次终于愿意将http编程模型的相关细节暴露给我们了.在之前的介绍中,基本上都基于.NET 4.5之后版本,其System.N ...
- WPF快速入门系列(1)——WPF布局概览
一.引言 关于WPF早在一年前就已经看过<深入浅出WPF>这本书,当时看完之后由于没有做笔记,以至于我现在又重新捡起来并记录下学习的过程,本系列将是一个WPF快速入门系列,主要介绍WPF中 ...
- [转]快速入门系列--WebAPI--01基础
本文转自:http://www.cnblogs.com/wanliwang01/p/aspnet_webapi_base01.html ASP.NET MVC和WebAPI已经是.NET Web部分的 ...
- vue 快速入门 系列 —— 初步认识 vue
其他章节请看: vue 快速入门 系列 初步认识 vue vue 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架. 所谓渐进式,就是你可以一步一步.有阶段 ...
随机推荐
- 【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
问题描述 当在App Service for Windows环境中所列出的Tomcat Version 没有所需要的情况下,如何实现自定义Tomcat 环境呢? 问题解答 第一步: 从官网下载要使用的 ...
- 代码随想录算法训练营第三十天| 51. N皇后 37. 解数独 总结
卡哥建议:今天这三道题都非常难,那么这么难的题,为啥一天做三道? 因为 一刷 也不求大家能把这么难的问题解决,所以 大家一刷的时候,就了解一下题目的要求,了解一下解题思路,不求能直接写出 ...
- 从源码看webpack3打包流程
在javascript刚刚流行时,前端项目通常比较简单,不需要考虑项目的开发效率.性能和扩展性等. 随着前端项目越来越复杂,需要更正式的软件开发实践,比如单元测试(unit testing).代码检查 ...
- 17. Class字节码指令解析
## 1. 概述 官方文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html Java 字节码对于虚拟机,就好像汇编语言对于 ...
- CYQ.Data 操作 Redis 性能测试:对比 StackExchange.Redis
前言: 前几天,点开自己的博客,看了一下 CYQ.Data V5系列 都有哪些文章, 发现了一篇2019年写的:CYQ.Data 对于分布式缓存Redis.MemCache高可用的改进及性能测试,于是 ...
- 关于Sql server数据类型HierarchyID 数据类型用法和递归显示完整路径
SQL Server 2008版本之后的新类型HierarchyID 不知道大家有没有了解, 该类型作为取代id, parentid的一种解决方案,让人非常惊喜. 官方给的案例浅显易懂,但是没有实现我 ...
- ElasticSearch - 基础概念和映射
前言 写这篇东西,是因为官方文档看着太痛苦,于是乎想用大白话来聊聊 ElasticSearc (下面都简称ES).所以下文对于 ES 一些概念的表述可能会与官方有出入,所以需要准确的表述和详细定义的, ...
- 记录--为什么要使用 package-lock.json?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 随着JavaScript在现代软件开发中的日益重要地位,Node.js生态系统中的npm成为了不可或缺的工具.在npm管理依赖的过程 ...
- elasticsearch中runtime_mapping实战
背景:需要根据一个实时计算处理的结果值进行排序,数据从es中查询.(基于业务背景:佣金排序) es版本:7.17.1:spring-data-elasticsearch版本:4.3.9 方式一:mys ...
- C#(winform)自定义ListItem类方便ComboBox操作
public class ListItem { /// <summary> /// Key /// </summary> public string Key { get; se ...