Vue Router 是 Vue 单页应用的核心,但基础的页面切换只是入门 ------ 实际开发中还需要处理导航高亮、页面重定向、404 错误、路由传参等场景。本文结合思维导图,带你掌握 Vue Router 的进阶用法。
一、声明式导航:更优雅的页面跳转
声明式导航通过<router-link>标签实现(替代传统<a>标签),核心优势是自带 "导航高亮" 能力。
1. 导航高亮:自动标识当前路由
<router-link>会自动给当前激活的路由添加类名,默认类名是router-link-active(模糊匹配)和router-link-exact-active(精确匹配)。
(1)两个类名的区别
router-link-active:模糊匹配(如/goods会匹配/开头的路由);router-link-exact-active:精确匹配(仅当路径完全一致时激活)。
示例:
vue
<template>
<!-- 点击"商品页"时,/goods会同时激活router-link-active和router-link-exact-active -->
<!--
router-link: VueRouter 提供的全局组件
必须提供 to 属性
1. 会自动加 #
2 可以很方便的实现导航高亮
-->
<router-link to="/">首页</router-link>
<router-link to="/goods">商品页</router-link>
</template>
<style>
/*
router-link-active: 模糊匹配, 只要访问路径包含 a 标签的 href, 就会自动加上这个类名 (用得多)
router-link-exact-active: 精确匹配, 必须要访问路径和 a 标签的 href 完全一致才会加上这个类名 (用得少)
*/
/* 自定义高亮样式 */
.router-link-exact-active {
color: red;
font-weight: bold;
}
</style>
(2)自定义高亮类名
若不想用默认类名,可通过active-class和exact-active-class自定义:
javascript
// 在index.js中
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
],
// 自定义模糊匹配的类名
linkActiveClass: 'active',
// 自定义精确匹配的类名
linkExactActiveClass: 'exact-active',
})
export default router
使用时,只需要用自己定义的类名即可
vue
<style>
a.active {
background-color: yellow;
}
</style>
2. 声明式导航传参:携带数据跳转
query传参是将参数拼接在 URL 的查询字符串中(如/goods?id=1&name=苹果),特点是参数可见、可刷新保留。
(1) 基本用法
通过<router-link>的to属性传递对象形式的query参数:
vue
<template>
<!-- 传参:query参数会拼接在URL后 -->
<router-link
:to="{
path: '/goods', // 目标路由路径
query: { id: 1, name: '苹果' } // 传递的参数
}">
苹果详情
</router-link>
<!-- 或使用这种方式 -->
<!-- <router-link :to="/goods?id=1&name=苹果">
苹果详情
</router-link> -->
</template>
(2)目标页面接收参数
在目标组件中,通过this.$route.query获取参数:
vue
<!-- Goods.vue -->
<script>
export default {
mounted() {
console.log(this.$route.query.id); // 输出:1
console.log(this.$route.query.name); // 输出:"苹果"
}
};
</script>
(3)特点
- 参数会显示在 URL 中,支持刷新页面后保留;
- 适合传递非敏感、可选的参数(如列表筛选条件)。
3. 声明式导航传参:动态路由传参
动态路由传参是将参数嵌入路由路径中(如/goods/1),特点是参数隐藏在路径中、语义化更强。
(1)配置动态路由规则
先在路由配置中定义动态路由参数(以:开头):
javascript
// router/index.js
const routes = [
// 动态路由:id是参数名
{ path: '/goods/:id', name: 'Goods', component: Goods }
];
(2)声明式导航传递动态参数
通过<router-link>的to属性传递动态参数:
vue
<template>
<!-- 方式1:直接拼接路径 -->
<router-link to="/goods/2">香蕉详情</router-link>
<!-- 方式2:结合命名路由(更灵活) -->
<router-link
:to="{
name: 'Goods', // 对应路由的name
params: { id: 3 } // 传递动态参数
}"
>
橙子详情
</router-link>
</template>
(3)目标页面接收参数
在目标组件中,通过this.$route.params获取参数:
vue
<!-- Goods.vue -->
<script>
export default {
mounted() {
console.log(this.$route.params.id); // 输出:2 或 3
}
};
</script>
(4)特点
- 参数隐藏在 URL 路径中,语义化更强(如
/goods/1比/goods?id=1更直观); - 适合传递必填的、标识性的参数(如商品 ID、用户 ID)。
4. 动态路由参数可选符:处理非必填参数
默认情况下,动态路由参数是必填的(如/goods/:id必须传入id,否则会匹配 404)。若需要参数可选,可在参数名后添加?(可选符)。
(1)配置可选动态路由
在路由规则的参数名后加?:
javascript
// router/index.js
const routes = [
// id参数可选:/goods 和 /goods/1 都能匹配
{ path: '/goods/:id?', name: 'Goods', component: Goods }
];
(2) 声明式导航使用
可选择是否传递参数:
vue
<template>
<!-- 不传递id参数,匹配/goods -->
<router-link to="/goods">商品列表</router-link>
<!-- 传递id参数,匹配/goods/4 -->
<router-link to="/goods/4">草莓详情</router-link>
</template>
(3)目标页面兼容处理
在目标组件中判断参数是否存在:
vue
<!-- Goods.vue -->
<script>
export default {
mounted() {
const goodsId = this.$route.params.id;
if (goodsId) {
console.log('当前是商品详情,ID:', goodsId);
} else {
console.log('当前是商品列表');
}
}
};
</script>
二、重定向:页面跳转的 "快捷方式"
重定向用于将一个路由自动跳转到另一个路由(如访问/home时跳转到/),通过路由规则的redirect属性实现。
javascript
// router/index.js 路由规则
const routes = [
{ path: '/', component: Home },
// 访问/home时,重定向到首页
{ path: '/home', redirect: '/' },
// 也可以重定向到命名路由(需给路由配置name)
{ path: '/old-goods', redirect: { name: 'Goods' } }
];
三、处理 404 页面:捕获无效路由
当用户访问不存在的路由时,需要显示 "404 页面"------ 通过通配符*匹配所有未定义的路由。
步骤:
1.创建 404 页面组件(如NotFound.vue);
vue
<template>
<div>
<img src="https://img2.baidu.com/it/u=1515291965,518622767&fm=253&fmt=auto&app=138&f=PNG?w=500&h=294" alt="">
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang="less">
div {
text-align: center;
img {
margin-top: 100px;
}
}
</style>
2.在路由规则最后添加通配符路由:
javascript
// router/index.js
import NotFound from '../views/NotFound.vue';
const routes = [
{ path: '/', component: Home },
{ path: '/goods', component: Goods },
// 通配符*匹配所有未定义的路由
{ path: '*', component: NotFound }
];
此时访问/abc等无效路径,会自动渲染NotFound.vue。
四、路由模式:控制 URL 的表现形式
Vue Router 有两种路由模式,决定 URL 的格式:
1. hash 模式(默认)
- URL 中包含
#(如http://localhost:8080/#/goods); - 优点:兼容性好(支持所有浏览器);
- 缺点:URL 不够美观。
2. history 模式
- URL 无
#(如http://localhost:8080/goods) - 优点:URL 更符合传统网站格式;
- 缺点:需要后端配合(部署时需配置 Nginx/Apache,否则刷新页面会 404)。
配置方式:
javascript
// router/index.js
const router = new VueRouter({
mode: 'history', // 切换为history模式
routes
});
五、编程式导航:通过 JS 控制跳转
编程式导航是通过 JavaScript 代码控制页面跳转的核心方式,而 Vue Router 中最常用的跳转逻辑可分为 path跳转和name跳转 两大类,每种方式又支持不同的传参策略。本文将这两种跳转方式与传参逻辑结合,帮你系统掌握编程式导航的用法。
1. 核心跳转方法:this.$router.push()
无论使用path还是name跳转,核心方法都是this.$router.push(),它接收一个路由地址参数(字符串或对象),并将新路由添加到浏览器历史记录中(支持后退)。
基础用法(无传参):
vue
// 字符串形式(仅path跳转可用)
this.$router.push('/home');
// 对象形式(path/name跳转均支持)
this.$router.push({ path: '/home' }); // path跳转
this.$router.push({ name: 'Home' }); // name跳转
2. 方式 1:path 跳转(通过路径匹配)
path跳转直接通过路由的路径(如/goods)匹配目标页面,传参方式有两种:query传参和动态路由params传参。
(1)path 跳转 + query 传参(最常用)
参数以查询字符串形式拼接在 URL 后(如 /goods?id=1&name=苹果 ),适合传递非敏感、可选参数。
用法示例:
javascript
this.$router.push({
path: '/goods', // 目标路由路径
query: {
id: 1,
name: '苹果',
price: 5.99
}
});
// 最终URL:/goods?id=1&name=苹果&price=5.99
目标页面接收参数:
javascript
// 目标组件中通过$route.query获取
mounted() {
console.log(this.$route.query.id); // 1
console.log(this.$route.query.name); // '苹果'
}
(2)path 跳转 + 动态路由 params 传参(需路由配置)
参数嵌入 URL 路径中(如/goods/1),适合传递标识性参数(如 ID),需在路由规则中定义动态参数(:开头)。
步骤 1:配置动态路由规则
javascript
// router/index.js
const routes = [
{ path: '/goods/:id', component: Goods } // 定义动态参数id
];
步骤 2:path 跳转传参
javascript
// 方式1:直接拼接路径(推荐)
this.$router.push(`/goods/${1}`); // 等价于 '/goods/1'
// 方式2:通过params对象传递(仅path为字符串时生效)
this.$router.push({
path: '/goods',
params: { id: 1 } // 解析为 '/goods/1'
});
目标页面接收参数:
javascript
// 目标组件中通过$route.params获取
mounted() {
console.log(this.$route.params.id); // 1
}
3. 方式 2:name 跳转(通过路由名称匹配)
name跳转通过路由规则中定义的name属性匹配页面(如name: 'Goods'),传参方式同样支持query和params,且更推荐用于复杂场景。
(1)name 跳转 + query 传参
与path跳转+query传参逻辑一致,参数显示在 URL 查询字符串中,但通过name匹配路由更易维护。
用法示例:
javascript
// 步骤1:路由规则定义name
// router/index.js
const routes = [
{ path: '/goods', name: 'Goods', component: Goods }
];
// 步骤2:name跳转传参
this.$router.push({
name: 'Goods', // 目标路由名称
query: {
id: 2,
name: '香蕉'
}
});
// 最终URL:/goods?id=2&name=香蕉
目标页面接收参数:
javascript
// 同样通过$route.query获取
console.log(this.$route.query.id); // 2
(2)name 跳转 + params 传参(推荐)
参数可嵌入路径(动态路由)或仅在内存中传递,无需手动拼接路径,灵活性更高。
步骤 1:配置带 name 的动态路由
javascript
// router/index.js
const routes = [
{ path: '/goods/:id', name: 'Goods', component: Goods }
];
步骤 2:name 跳转传参
javascript
this.$router.push({
name: 'Goods',
params: {
id: 2, // 动态参数(会嵌入URL:/goods/2)
type: 'fruit' // 非动态参数(仅内存传递,刷新丢失)
}
});
目标页面接收参数:
javascript
// 动态参数和非动态参数均通过$route.params获取
mounted() {
console.log(this.$route.params.id); // 2(URL中可见)
console.log(this.$route.params.type); // 'fruit'(仅内存中)
}