vue3 快速入门系列 - vue3 路由

vue3 基础上加入路由。

vue3 需要使用 vue-router V4,相对于 v3,大部分的 Vue Router API 都没有变化。

Tip:不了解路由的同学可以看一下笔者之前的文章:vue2 路由

参考:vue2 路由官网vue3 路由官网

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>

编程式导航

Tipvue2 路由 -> 编程式导航

三秒后跳转到 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 路由的更多相关文章

  1. 快速入门系列--MVC--02路由

    现在补上URL路由的学习,至于蒋老师自建的MVC小引擎和相关案例就放在论文提交后再实践咯.通过ASP.NET的路由系统,可以完成请求URL与物理文件的分离,其优点是:灵活性.可读性.SEO优化.接下来 ...

  2. 快速入门系列--MVC--01概述

    虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入.其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的 ...

  3. 快速入门系列--MVC--07与HTML5移动开发的结合

    现在移动互联网的盛行,跨平台并兼容不同设备的HTML5越来越盛行,很多公司都在将自己过去的非HTML5网站应用渐进式的转化为HTML5应用,使得一套代码可以兼容不同的物理终端设备和浏览器,极大的提高了 ...

  4. vue 快速入门 系列 —— vue-cli 上

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 上 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  5. 快速入门系列--WebAPI--01基础

    ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因 ...

  6. 快速入门系列--WebAPI--03框架你值得拥有

    接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...

  7. 快速入门系列--WebAPI--04在老版本MVC4下的调整

    WebAPI是建立在MVC和WCF的基础上的,原来微软老是喜欢封装的很多,这次终于愿意将http编程模型的相关细节暴露给我们了.在之前的介绍中,基本上都基于.NET 4.5之后版本,其System.N ...

  8. WPF快速入门系列(1)——WPF布局概览

    一.引言 关于WPF早在一年前就已经看过<深入浅出WPF>这本书,当时看完之后由于没有做笔记,以至于我现在又重新捡起来并记录下学习的过程,本系列将是一个WPF快速入门系列,主要介绍WPF中 ...

  9. [转]快速入门系列--WebAPI--01基础

    本文转自:http://www.cnblogs.com/wanliwang01/p/aspnet_webapi_base01.html ASP.NET MVC和WebAPI已经是.NET Web部分的 ...

  10. vue 快速入门 系列 —— 初步认识 vue

    其他章节请看: vue 快速入门 系列 初步认识 vue vue 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架. 所谓渐进式,就是你可以一步一步.有阶段 ...

随机推荐

  1. 有了这份Java面试中的葵花宝典,让你面试起飞!!!

    HashMap面试题 HashMap与HashTable的区别 1.HashMap线程不安全 HashTable 线程是安全的采用synchronized 2.HashMap允许存放key 为null ...

  2. 在Bind DNS Server中添加一个开发环境的域名

    1.Create Master Zone 我们的开发域名约定为dudusoft.cn 输入2个字段,然后提交 2.在域名里面,添加主机记录 点击上图的"Address(0)",出现 ...

  3. 文心一言 VS 讯飞星火 VS chatgpt (204)-- 算法导论15.3 3题

    三.考虑矩阵链乘法问题的一个变形:目标改为最大化矩阵序列括号化方案的标量乘法运算次数,而非最小化.此问题具有最优子结构性质吗?需要写代码的时候,请用go语言. 文心一言,代码正常运行: 首先,我们要明 ...

  4. 【Azure 应用服务】App Service For Linux 环境中,如何修改 Nginx 配置中 server_name的默认值 example.com

    问题描述 在App Service for Linux环境中,部署PHP应用,使用Nginx服务器.因为PHP应用中所有静态资源的URL使用的默认域名为 https://example.com:808 ...

  5. sqlmap 绕过WAF

    1.基本的语法 sqlmap 更新  sqlmap -update 具体的使用方法: sqlmap -u url --current-user sqlmap -u url --current-db s ...

  6. 如何将应用一键部署至多个环境?丨Walrus教程

    在 Walrus 平台上,运维团队在资源定义(Resource Definition)中声明提供的资源类型,通过设置匹配规则,将不同的资源部署模板应用到不同类型的环境.项目等.与此同时,研发人员无需关 ...

  7. Obsidian 0.15.9 知识笔记 使用说明

    我感觉这个软件是一个非常好用的软件,经过初步体验. 全局搜索快捷键 Ctrl + Shift + F 打开快速切换快捷键 Ctrl + O 添加标签 #测试标签 反向链接 Obsidian支持反向链接 ...

  8. 音标 舌侧音 /l/ 的发音 - 英语

    音标 舌侧音 /l/ 的发音 这个音标 首先确定下 就是一个音 发 了(注意 发音方式不是中文的了,是英文的了) 注意发音方式很重要 中文 '了',重点在 偏鼻音(发射方向为前上方) 英文 '了',重 ...

  9. 【LLM】在Colab上使用免费T4 GPU进行Chinese-Llama-2-7b-4bit推理

    一.配置环境 1.打开colab,创建一个空白notebook,在[修改运行时环境]中选择15GB显存的T4 GPU. 2.pip安装依赖python包 !pip install --upgrade ...

  10. opus编解码的特色和优点

    概念原理   Opus是一个有损音频压缩的数字音频编码格式,由Xiph.Org基金会开发,之后由互联网工程任务组(IETF)进行标准化,目标是希望用单一格式包含声音和语音,取代Speex和Vorbis ...