1、路由基础
在单页 Web 应用中,整个项目只有一个 HTML 文件,不同视图(组件的模块)的内容都是在同一个页面中渲染的。当用户切换页面时,页面之前的跳转都是在浏览器端完成的,这时就需要使用前端路由。
路由实际上就是一种映射关系。例如,多个选项卡之间的切换就可以使用路由功能来实现。在切换时,根据鼠标的点击事件显示不同的页面内容,这相当于事件和事件处理程序之间的映射关系。
1.1 引入 Vue Router
在使用 Vue Router 之前需要在页面中进行引入,可以使用 CDN 方式引入 Vue Router。代码如下:
<script src="https://unpkg.com/vue-router@next"></script>
如果在项目中 Vue Router,则可以使用 npm 方式进行安装。在命令提示符窗口中输入如下命令:
npm install vue-router@next --save
说明:
在安装 Vue Router 时,要安装支持 Vue 3.0 版本的 Vue Router 需要使用 vue-router@next,要安装支持 Vue 2.x 版本的 Vue Router 需要使用 vue-router。
1.2 基本用法
使用 Vue.js 创建的应用程序可以由多个组件组成,而 Vue Router 的作用是将每个路径映射到对应的组件,并通过路由进行组件之间的切换。
Vue.js 路由的思想是通过不同的 URL 访问不同的内容。要想通过路由实现组件之间的切换,需要使用 Vue Router 提供的 <router-link> 组件,该组件用于设置一个导航链接,通过设置 to 属性链接到一个目标地址,从而切换不同的 HTML 内容。实际的浏览器页面中 <router-link> 组件默认会被渲染成 <a> 标签。下面是一个实现路由的简单示例,实现步骤如下。
(1)使用 <router-link> 组件设置导航链接。
<!-- 使用 router-line 组件设置导航 -->
<router-link to="/">首页</router-link>
<router-link to="/course/list">课程</router-link>
<router-link to="/about">关于</router-link>
(2)通过 <router-view> 指定组件在何处渲染。
<!-- 路由出口,路由配置到的组件渲染的位置 -->
<router-view></router-view>
1.3 命名路由
在某些时候,在进行路由跳转时,通过一个名称来标识路由会更方便一些。可以在创建 Vue Router 实例时,在 routes 配置中为某个路由设置名称。
示例代码如下:
const routes = [
{
path: '/course/list',
name: 'courseList',
component: CourseView,
meta: {
title: '课程列表'
}
}
]
在设置了路由的名称后,要想链接到该路径,可以将 <router-link> 组件的 to 属性设置成一个对象,同时需要使用 v-bind 指令。
代码如下:
<router-link :to="{ name: 'courseList' }">课程</router-link>
这样,当点击“课程”链接时,会跳转到 /course/list 路径的路由。
2、通过 URL 传递与获取参数
在实际的开发中,经常需要通过URL来传递参数,同时在 JavaScript 脚本中需要获取URL中的参数。
2.1 传递 URL 参数
(1)配置路由信息:
const routes = [
{
path: '/course/detail/:id',
name: 'courseDetail',
component: CourseDetail,
meta: {
title: '课程详情'
}
}
]
该路由配置的 path 值为: '/course/detail/:id',其中 :id 为参数的占位符,需要通过 params:{} 方式赋值 。有效地址例如:/course/detail/1 或者 /course/detail/2 等。
(2)URL参数的传递:
<router-link :to="{ name: 'courseDetail', params: { id: course.id }, query: { name: course.name, teacher: course.teacher } }">预览</router-link>
参数说明:
params 参数:会在URL中显示出传参的值,刷新页面不会丢失参数,使用该方式传值的时候,需要在路由提前配置好参数,如上述代码:path: '/course/detail/:id',其中 :id 为参数的占位符。
query 参数:传递的参数会拼接在地址栏中(?name=xxx&teacher=xxx),刷新页面不会丢失参数,使用 path 和 name 都可以。
执行结果:
关于通过 URL 传递与获取参数的详细介绍,请点击浏览文章:《Vue使用Vue Router路由:通过URL传递与获取参数》
2.2 获取 URL 参数
(1)模板中获取URL参数:
<!-- 获取 params 对象中的参数 -->
<p>课程编号:{{ $route.params.id }}</p>
<!-- 获取 query 对象中的参数 -->
<p>课程名称:{{ $route.query.name }}</p>
<p>课程讲师:{{ $route.query.teacher }}</p>
(2)JavaScript 中获取URL参数(Vue 2.0):
this.id = this.$route.params.Id || 0; //获取 params 对象中的参数
this.name = this.$route.query.name; //获取 query 对象中的参数
(3)JavaScript 中获取URL参数(Vue 3.0 ):
import { useRoute } from 'vue-router';
//获取URL参数
const route = useRoute();
let id = route.params.id || 0; //获取 params 对象中的参数
let name = route.query.name; //获取 query 对象中的参数
let teacher = route.query.teacher;
//打印参数
console.log("获取URL参数id:", id);
console.log("获取URL参数name:", name);
console.log("获取URL参数teacher:", teacher);
执行结果:
3、编程式导航
定义导航链接除了使用 <router-link> 组件创建 <a> 标签,还可以使用 router 实例的 push() 方法实现导航的功能。在 Vue 2.0 实例内部,通过 $router 可以访问路由实例,因此通过调用 this.$router.push()函数即可实现页面的跳转。
该方法的参数可以是一个字符串路径,还可以是一个描述跳转目的地址的对象。
Vue 2.0 使用编程式导航:
//跳转到字符串表示的链接
this.$router.push('music')
//跳转到指定链接
this.$router.push({ path: 'music' })
//跳转到指定命名的路由
this.$router.push({ name: 'user' })
//跳转到带有查询参数的指定路径
this.$router.push({ path: 'music', query: { id: '5' }})
//跳转到带有查询参数的指定命名的路由
this.$router.push({ name: 'user', params: { id: '1' }})
Vue 3.0 使用编程式导航:
<script setup>
//引用 router 对象
import router from '@/router';
//跳转到字符串表示的链接
router.push('music')
//跳转到指定链接
router.push({ path: 'music' })
//跳转到指定命名的路由
router.push({ name: 'user' })
//跳转到带有查询参数的指定路径
router.push({ path: 'music', query: { id: '5' }})
//跳转到带有查询参数的指定命名的路由
router.push({ name: 'user', params: { id: '1' }})
</script>
4、高级用法
4.1 beforeEach 钩子函数
beforeEach 是 Vue Router 提供的一个钩子函数,该函数会在路由即将发生变化之前触发。使用 beforeEach 钩子函数,可以在路由发生变化时进行一些特殊的处理。
函数语法如下:
router.beforeEach((to, from, next) => {
//忽略代码...
});
参数说明:
to:即将进入的目标路由对象。
from:当前导航即将离开的路由对象。
next:调用该方法后进入下一个钩子。
在设置网页标题时经常会用到 beforeEach 钩子函数。因为单页应用只有一个固定的 HTML,当使用路由切换到不同页面时,HTML 标题并不会发生变化。这时就可以使用 beforeEach 钩子函数来设置网页的标题。
【实例】使用 beforeEach 钩子函数,设置网页的标题。
router.beforeEach((to, from, next) => {
//设置网页标题
document.title = to.meta.title;
next();
});
4.2 scrollBehavior 方法
在单页应用中使用路由功能,如果在切换到新的路由之前页面中出现了滚动条,那么在默认情况下,切换路由之后的页面并不会滚动到顶部。如果想要使页面滚动到顶部,或者保持原来的滚动位置,需要使用 Vue Router 提供的 scrollBehavior 方法。该方法可以自定义路由切换时页面如何滚动。
方法的语法格式如下:
scrollBehavior(to, from, savedPosition){
//return 期望滚动到哪个位置
}
参数说明:
to:即将进入的目标路由对象。
from:当前导航即将离开的路由对象。
savedPosition:当前导航通过浏览器的前进或后退按钮触发时才可用。
5、创建一个单页应用
【实例】使用Vue Router,开发一个单页应用,该应用包含三个导航:首页、课程、关于,其中课程包含课程列表和课程详情。执行结果如下图:
(1)首页:
(2)课程列表页面:
(3)关于页面:
以下是完整代码:
首先创建一个 Vue 项目,详细的创建项目的过程,请点击浏览文章:《使用Vue CLI方式创建Vue3.0应用程序》
注意:在创建项目的过程中,一定要选择 Router 路由选项。
(1)创建首页:HomeView.vue 组件。
<template>
<h3>首页</h3>
<p>博客信息:{{ blogInfo.blogName }}</p>
<p>博客地址:{{ blogInfo.blogUrl }}</p>
</template>
<script setup>
import { ref } from 'vue';
// 使用 ref 创建响应式的对象
const blogInfo = ref({
blogName: '您好,欢迎访问 pan_junbiao的博客',
blogUrl: 'https://blog.csdn.net/pan_junbiao'
});
</script>
(2)创建课程列表:CourseView.vue 组件,并绑定课程列表数据。
<template>
<h3>课程列表</h3>
<table>
<tr>
<th>编号</th>
<th>课程名称</th>
<th>讲师</th>
<th>操作</th>
</tr>
<tr v-for="(course, index) in courseList" :key="index">
<td>{{ course.id }}</td>
<td>{{ course.name }}</td>
<td>{{ course.teacher }}</td>
<td><router-link :to="{ name: 'courseDetail', params: { id: course.id }, query: { name: course.name, teacher: course.teacher } }">预览</router-link>
</td>
</tr>
</table>
</template>
<script setup>
import { ref } from 'vue';
//课程列表:使用 ref 创建响应式的对象
const courseList = ref([
{ id: 1, name: 'Java', teacher: '张老师' },
{ id: 2, name: 'HTML5', teacher: '黄老师' },
{ id: 3, name: 'CSS3', teacher: '李老师' },
{ id: 4, name: 'Vue 3.0', teacher: '童老师' }
]);
</script>
<!-- CSS样式 -->
<style scoped>
table {
border-collapse: collapse;
}
table,
table tr th,
table tr td {
border: 1px solid #000000;
padding: 5px;
}
</style>
(3)创建关于:AboutView.vue 组件。
<template>
<h3>关于</h3>
<p>博客信息:{{ blogInfo.blogName }}</p>
<p>博客地址:{{ blogInfo.blogUrl }}</p>
</template>
<script setup>
import { ref } from 'vue';
// 使用 ref 创建响应式的对象
const blogInfo = ref({
blogName: '您好,欢迎访问 pan_junbiao的博客',
blogUrl: 'https://blog.csdn.net/pan_junbiao'
});
</script>
(4)创建课程详情:CourseDetail.vue 组件,并通过获取URL参数,绑定课程详情信息,实现路由的跳转。
<template>
<h3>课程详情</h3>
<!-- 获取 params 对象中的参数 -->
<p>课程编号:{{ $route.params.id }}</p>
<!-- 获取 query 对象中的参数 -->
<p>课程名称:{{ $route.query.name }}</p>
<p>课程讲师:{{ $route.query.teacher }}</p>
<button @click="toCoureLisr">返回列表页面</button>
</template>
<!-- 使用 <script setup> 语法糖 -->
<script setup>
import { onMounted } from 'vue';
import { useRoute } from 'vue-router';
import router from '@/router';
onMounted(() => {
//获取URL参数
const route = useRoute();
let id = route.params.id || 0; //获取 params 对象中的参数
let name = route.query.name; //获取 query 对象中的参数
let teacher = route.query.teacher;
//打印参数
console.log("获取URL参数id:", id);
console.log("获取URL参数name:", name);
console.log("获取URL参数teacher:", teacher);
})
//返回列表页面
function toCoureLisr() {
//实现路由的跳转
router.push({ name: 'courseList' });
}
</script>
(5)配置 Vue Router 路由信息:打开 router 目录,编辑该目录下的 index.js 文件。
import { createRouter, createWebHashHistory } from 'vue-router'
// 导入组件
import HomeView from '@/views/HomeView.vue';
import CourseView from '@/views/CourseView.vue';
import CourseDetail from '@/views/CourseDetail.vue';
import AboutView from '@/views/AboutView.vue';
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
meta: {
title: '首页'
}
},
{
path: '/course/list',
name: 'courseList',
component: CourseView,
meta: {
title: '课程列表'
}
},
{
path: '/course/detail/:id',
name: 'courseDetail',
component: CourseDetail,
meta: {
title: '课程详情'
}
},
{
path: '/about',
name: 'about',
component: AboutView,
meta: {
title: '关于'
}
}
]
//创建 VueRouter 实例,传入路由配置
const router = createRouter({
history: createWebHashHistory(),
routes: routes
});
//钩子函数:beforeEach:该函数会在路由即将发生改变之前触发
router.beforeEach((to, from, next) => {
//设置网页标题
document.title = to.meta.title;
next();
});
export default router;
(6)设置导航:修改 App.vue 根组件文件,使用 <router-link> 组件设置导航,使用 <router-view> 组件设置路由的渲染窗口。
<template>
<!-- 使用 router-line 组件设置导航 -->
<router-link to="/">首页</router-link>
<router-link to="/course/list">课程</router-link>
<router-link to="/about">关于</router-link>
<!-- 路由出口,路由配置到的组件渲染的窗口 -->
<router-view></router-view>
</template>
<style scoped>
a {
margin-right: 10px;
}
</style>
执行结果:
(1)课程列表页面:
(2)课程详情页面: