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:精确匹配(仅当路径完全一致时激活)。
示例:
<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自定义:
// 在index.js中importVuefrom'vue'importVueRouterfrom'vue-router'Vue.use(VueRouter)constrouter=newVueRouter({routes:[],// 自定义模糊匹配的类名linkActiveClass:'active',// 自定义精确匹配的类名linkExactActiveClass:'exact-active',})exportdefaultrouter使用时,只需要用自己定义的类名即可
<style> a.active { background-color: yellow; } </style>2. 声明式导航传参:携带数据跳转
query传参是将参数拼接在 URL 的查询字符串中(如/goods?id=1&name=苹果),特点是参数可见、可刷新保留。
(1) 基本用法
通过<router-link>的to属性传递对象形式的query参数:
<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获取参数:
<!-- 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)配置动态路由规则
先在路由配置中定义动态路由参数(以:开头):
// router/index.jsconstroutes=[// 动态路由:id是参数名{path:'/goods/:id',name:'Goods',component:Goods}];(2)声明式导航传递动态参数
通过<router-link>的to属性传递动态参数:
<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获取参数:
<!-- 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)配置可选动态路由
在路由规则的参数名后加?:
// router/index.jsconstroutes=[// id参数可选:/goods 和 /goods/1 都能匹配{path:'/goods/:id?',name:'Goods',component:Goods}];(2) 声明式导航使用
可选择是否传递参数:
<template> <!-- 不传递id参数,匹配/goods --> <router-link to="/goods">商品列表</router-link> <!-- 传递id参数,匹配/goods/4 --> <router-link to="/goods/4">草莓详情</router-link> </template>(3)目标页面兼容处理
在目标组件中判断参数是否存在:
<!-- Goods.vue --> <script> export default { mounted() { const goodsId = this.$route.params.id; if (goodsId) { console.log('当前是商品详情,ID:', goodsId); } else { console.log('当前是商品列表'); } } }; </script>二、重定向:页面跳转的 “快捷方式”
重定向用于将一个路由自动跳转到另一个路由(如访问/home时跳转到/),通过路由规则的redirect属性实现。
// router/index.js 路由规则constroutes=[{path:'/',component:Home},// 访问/home时,重定向到首页{path:'/home',redirect:'/'},// 也可以重定向到命名路由(需给路由配置name){path:'/old-goods',redirect:{name:'Goods'}}];三、处理 404 页面:捕获无效路由
当用户访问不存在的路由时,需要显示 “404 页面”—— 通过通配符*匹配所有未定义的路由。
步骤:
1.创建 404 页面组件(如NotFound.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.在路由规则最后添加通配符路由:
// router/index.jsimportNotFoundfrom'../views/NotFound.vue';constroutes=[{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)。
配置方式:
// router/index.jsconstrouter=newVueRouter({mode:'history',// 切换为history模式routes});五、编程式导航:通过 JS 控制跳转
编程式导航是通过 JavaScript 代码控制页面跳转的核心方式,而 Vue Router 中最常用的跳转逻辑可分为path跳转和name跳转两大类,每种方式又支持不同的传参策略。本文将这两种跳转方式与传参逻辑结合,帮你系统掌握编程式导航的用法。
1. 核心跳转方法:this.$router.push()
无论使用path还是name跳转,核心方法都是this.$router.push(),它接收一个路由地址参数(字符串或对象),并将新路由添加到浏览器历史记录中(支持后退)。
基础用法(无传参):
// 字符串形式(仅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=苹果 ),适合传递非敏感、可选参数。
用法示例:
this.$router.push({path:'/goods',// 目标路由路径query:{id:1,name:'苹果',price:5.99}});// 最终URL:/goods?id=1&name=苹果&price=5.99目标页面接收参数:
// 目标组件中通过$route.query获取mounted(){console.log(this.$route.query.id);// 1console.log(this.$route.query.name);// '苹果'}(2)path 跳转 + 动态路由 params 传参(需路由配置)
参数嵌入 URL 路径中(如/goods/1),适合传递标识性参数(如 ID),需在路由规则中定义动态参数(:开头)。
步骤 1:配置动态路由规则
// router/index.jsconstroutes=[{path:'/goods/:id',component:Goods}// 定义动态参数id];步骤 2:path 跳转传参
// 方式1:直接拼接路径(推荐)this.$router.push(`/goods/${1}`);// 等价于 '/goods/1'// 方式2:通过params对象传递(仅path为字符串时生效)this.$router.push({path:'/goods',params:{id:1}// 解析为 '/goods/1'});目标页面接收参数:
// 目标组件中通过$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匹配路由更易维护。
用法示例:
// 步骤1:路由规则定义name// router/index.jsconstroutes=[{path:'/goods',name:'Goods',component:Goods}];// 步骤2:name跳转传参this.$router.push({name:'Goods',// 目标路由名称query:{id:2,name:'香蕉'}});// 最终URL:/goods?id=2&name=香蕉目标页面接收参数:
// 同样通过$route.query获取console.log(this.$route.query.id);// 2(2)name 跳转 + params 传参(推荐)
参数可嵌入路径(动态路由)或仅在内存中传递,无需手动拼接路径,灵活性更高。
步骤 1:配置带 name 的动态路由
// router/index.jsconstroutes=[{path:'/goods/:id',name:'Goods',component:Goods}];步骤 2:name 跳转传参
this.$router.push({name:'Goods',params:{id:2,// 动态参数(会嵌入URL:/goods/2)type:'fruit'// 非动态参数(仅内存传递,刷新丢失)}});目标页面接收参数:
// 动态参数和非动态参数均通过$route.params获取mounted(){console.log(this.$route.params.id);// 2(URL中可见)console.log(this.$route.params.type);// 'fruit'(仅内存中)}