路由
Vue 3 中的路由管理主要通过Vue Router
实现。Vue Router
是 Vue.js 的官方路由管理器,能够帮助你轻松地在 Vue 应用中实现路由功能,使得不同的 URL 可以显示不同的组件,从而提升用户体验。
1.Vue Router
基础介绍
-
路由: 路由指的是 URL 到视图(组件)的映射关系。通过路由,可以根据不同的 URL 显示不同的组件。
-
单页面应用(SPA) : 在单页面应用中,所有的内容在一个页面中进行动态加载,用户不需要每次都刷新页面,从而提升了用户体验。
Vue Router
使得在 SPA 中实现路由管理变得简单。 -
路由模式:
Vue Router
提供了两种主要的路由模式:- Hash模式:使用 URL 的 hash(#)部分来实现路由,URL 看起来像
http://example.com/#/home
。优点是简单、兼容性好。 - History模式:使用 HTML5 的 History API,可以实现更为美观的 URL,例如
http://example.com/home
。需要后端支持配置,以确保所有请求都返回index.html
。
- Hash模式:使用 URL 的 hash(#)部分来实现路由,URL 看起来像
2.Vue Router
路由器的基础配置使用
2.1.路由器的配置
首先,要在 Vue 3 项目中使用Vue Router
,需要安装它:
npm install vue-router
通常在src
源文件目录下,建立router
文件夹以存储配置路由的js
或ts
文件,这里是一个示例:
//创建一个路由器,并暴露出去
//第一步:引入vue-router
import {createRouter,createWebHistory} from "vue-router";
//引入一个个可能呈现的组件
import Home from "@/pages/Home.vue";
import About from "@/pages/About.vue";
import News from "@/pages/News.vue"
//第二步:创建路由器
const router = createRouter(
{
history:createWebHistory(),//路由器的工作模式
routes:[
{
path:"/Home",
component: Home
},
{
path:"/News",
component: News
},
{
path:"/About",
component: About
},
]
}
)
//第三步:暴露出去
export default router
2.2.路由器的使用
我们仅仅是配置好了路由器后,我们需要在main.js
或main.ts
中引入配置好的路由:
import { createApp } from 'vue'
import App from './App.vue'
//引入路由器
import router from "@/router";
//创建一个应用
const app = createApp(App)
//使用路由器
app.use(router)
//挂载整个应用
app.mount('#app')
在我们的app应用中引入路由器后,我们便可以在某个Vue组件中对应的地方使用路由器,包括执行怎样的操作,对应哪条路由
首先,引入vue-router
依赖,它提供了调用路由器进行一些操作的接口:
<RouterLink>
:提供了类似超链接<a>
的链接路由的作用,它封装好了许多属性,如to
实现对应哪条路由、active-class
实现点击后添加类样式等<RouterView>
:便是提供将各条路由对应的组件挂载展示的标签
import { RouterView, RouterLink } from "vue-router";
接着便可在模板标签中调用路由器,这里是一条示例:
<template>
<div class="app">
<h2 class="title">Vue路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<RouterLink to="/Home" active-class="active">首页</RouterLink>
<RouterLink to="/News" active-class="active">新闻</RouterLink>
<RouterLink :to="{ path: '/About' }" active-class="active">关于</RouterLink>
</div>
<!-- 展示区 -->
<div class="main-content">
<RouterView />
</div>
</div>
</template>
<script setup>
import { RouterView, RouterLink } from "vue-router";
</script>
<style scoped>
//...
</style>
两个注意点
- 路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。- 通过点击导航,视觉效果上消失了的路由组件,默认是被卸载掉的,需要的时候再去挂载,
3.路由器的工作模式
3.1history
模式
优点:URL
更加美观,不带有#
,更接近传统网站的URL
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404
错误(无法找到路径)
使用示例:
import {createRouter,createWebHistory} from "vue-router";
const router = createRouter({
history:createWebHistory(),
//......
})
3.2hash
模式
优点:兼容性更好,因为不需要服务器端处理路径
缺点:URL
带有#
不太美观,且在SE0
优化方面相对较差
使用示例:
import {createRouter,createHashHistory} from "vue-router";
const router createRouter(
history:createHashHistory(),//hash模式
//.....
)
4.to
的两种写法
4.1.to
的字符串写法
<!-- 第一种:t0的字符串写法 -->
<router-link active-class="active" to="/home">Home</router-link>
4.2.to
的对象写法
<! -- 第二种:t0的对象写法 -->
<router-link active-class="active" to="{path:'/home'}">Home</router-link>
温馨提示
表面上看上去似乎第一种更简单,但在实际开发中,遇到需要给路由传入参数的情况,第二种写法才是最优解
5.路由的嵌套
在开发中我们会面临到这样一种情况:首页=>一级路由=>二级路由,相当于不断地在嵌套SPA
,因此Vue3也提供了嵌套路由的技术
5.1.路由器中配置子路由
首先,在路由器中配置,一级路由对应的二级路由,这里也是提供了属性children
用于存储配置的二级路由,当然二级路由对应的组件要先写好,这里是一个子路由配置示例:
const router = createRouter(
{
history:createWebHistory(),
routes:[
{
path:"/Home",
component: Home
},
//在一级路由News中添加了二级路由details
{
path:"/News",
component: News,
children:[
{
path:"detail",
component: Detail
}
]
},
{
path:"/About",
component: About
},
]
}
)
温馨提示
- 要先引入子路由对应组件
- 二级路由的
path
属性不加'/'
5.2.子路由的使用
与 【2.2.路由器的使用】 介绍的类似,在一级路由中引入vue-router
依赖后,创建相应位置所需的<RouterLink>
和<RouterView>
,便能实现路由的嵌套
温馨提示
子路由的路径添加在
<RouterLink>
中的to
时,需要注意以"/一级路由/二级路由"的形式引用,否则若直接引用二级路由,将无法找到对应路由,什么都不会显示,下面是一个示例:
<RouterLink to="/News/detail">xxx</RouterLink>
6.路由的传入参数
在开发工程中,我们常常需要向子路由中传入参数,以实现在一级路由组件中对不同元素的操作,来请求不同的子路由。
以新闻这一主题为例,假设新闻组件对应一个一级路由,而这个新闻组件中,有许多不同新闻的标题,点击不同的标题能够显示标题对应的新闻内容,而新闻内容这部分便对应一个二级路由,那么再假设我们不使用传入参数这一形式,那么有多少个新闻标题我们便需要写多少个新闻内容的二级路由,这样相同的代码冗余过多,不利于维护,与Vue组件式开发的初衷相违背。
因此,在这个例子中,我们若能给新闻内容的二级路由传入新闻标题对应的唯一标识key
值,便能通过这个key
值实现对新闻内容组件的动态渲染,不仅减少了代码文件的冗余,而且在维护时,只需要更新修改新闻内容组件中的数据即可。
6.1路由的query
参数
第一种写法:通过地址传入参数
首先,同样以新闻主题为例子,在新闻一级路由中的示例:
<li v-for:="news in newsList" :key="news.id">
<RouterLink :to="`/News/detail?id=${news.id}&title=${news.title}&content=${news.content}`">{{ news.title }}</RouterLink>
</li>
这里通过v-bind
指令和模板字符串的形式在路径后使用?
传入参数,多个参数间使用&
连接,传入给二级路由新闻的id,title,content数据。
接着,在二级路由中使用useRoute
接受来自一级路由的数据,将数据赋给一个变量,下面是一个示例:
import { useRoute } from "vue-router";
let route = useRoute();
console.log(route);
自此,一级路由的数据已成功传给二级路由,只需简单的在模板中调用即可,下面是一个示例:
<template>
<div>
<ul class="class-list">
<li>编号:{{ route.query.id }}</li>
<li>标题:{{ route.query.title }}</li>
<li>内容:{{ route.query.content }}</li>
</ul>
</div>
</template>
温馨提示
这里的
query
是reactive
类型响应式数据对象proxy
的一个存储数据的属性
第二种写法:通过对象中query
传入参数
参照 【4.2.to
的对象写法】 ,加入query
属性也可传入相应数据,下面是一个示例:
<li v-for:="news in newsList" :key="news.id">
<RouterLink :to="{
path: `/News/detail`,
query: {
id: news.id,
title: news.title,
content: news.content,
},
}">{{ news.title }}</RouterLink>
</li>
6.2.路由的params
参数
此方法是在URL
上作文章的,不再过多赘述
首先在path
中作出预置位,下面是一个示例:
const routes = [
{
path: '/user/:id',
component: UserProfile,
},
{
path: '/search',
component: SearchResults,
},
];
接着,在<RouterLink>
中传入参数,在路径后加入需要传入的数据即可,下面是一个示例:
<template>
<div id="app">
<router-link to="/user/1">Go to User 1 Profile</router-link>
<router-view></router-view>
</div>
</template>
备注1:传递
params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。 备注2:传递params
参数时,需要提前在规则中占位。
7.路由的props
接受参数配置
上节介绍了传入参数的方法,但在接收参数过程中仍采用这种接收办法:
<template>
<div>
<ul class="class-list">
<li>编号:{{ route.query.id }}</li>
<li>标题:{{ route.query.title }}</li>
<li>内容:{{ route.query.content }}</li>
</ul>
</div>
</template>
可见仍有过多的代码冗余,因此Vue3提供了在路由配置时props
的使用办法:
//props的对象写法,作用:把对象中的每一组key-value作为props传给Deta1l组件
//props:{a:1,b:2,c:3},
//props的布尔值写法,作用:把收到了每一组params参数,作为props传给Deta11组件
//props:true
//propsi的函数写法,作用:把返回的对象中每一组key-value作为props传给Deta1l组件
props(route){
console.log(route.query);
return route.query
},
在相应的路由组件中:
import { defineProps } from "vue";
defineProps(["id", "title", "content"]);
8.路由的replace
历史记录属性
作用:控制路由跳转时操作浏览器历史记录的模式
浏览器历史记录有两种写入方式:分别为push
和replace
push
:追加历史记录(默认值)replace
:替换当前记录
开启replace
模式:
<RouterLink replace ....>News</RouterLink>
9.编程式路由导航
脱离<RouterLink>
实现路由跳转 ,即不在模板元素中实现路由跳转,而是在脚本<script>
中实现。
在模板元素中的路由跳转就是通过<RouterLink>
,而它的本质实际上是对<a>
的封装。通过对其属性的操作,能很容易实现路由的跳转,但是在面对复杂的需求时,这种方法便很不灵活。
例如一个简单的用户登录功能,需要根据用户输入信息在服务器数据库中检索才能实现路由的跳转,这便需要在脚本中先与服务器交互,再操作路由跳转。编程式导航应运而生。
在<script>
脚本中操作路由跳转的办法,下面是一个示例:
import { useRouter } from "vue-router";
//获取当前路由器对象
const router = useRouter();
//与模板元素交互的的接口函数
function ShowDetails(News) {
//对当前路由器对象push路由跳转的信息
router.push({
path: `/News/detail`,
query: {
id: News.id,
title: News.title,
content: News.content,
},
});
}
示例中仅仅是与模板元素的交互接口,实际开发中还可以与例如计时器、与服务器交互等结合使用。
温馨提示
router.push()
的push()
括号里的内容就是<RouterLink>
中to
属性写的内容,具体可见 【4.to
的两种写法】- 这里的
push()
是类似栈的追加历史记录的浏览器写入方式,也可以用replace()
不保留历史记录写入
10.路由的重定向
让指定的路径重新定位到另一个路径 ,下面是一个在一级路由中的示例:
{
path:"/",
redirect:"/Home"
}