Vue Router的router-link该怎么用?常见问题有哪些?
很多刚接触Vue.js做前端路由跳转的同学,对router-link组件肯定又好奇又有点懵——它和普通a标签有啥区别?什么时候该用它?碰到样式不生效、跳转异常这些问题咋解决?今天就围绕router-link,把用法、特性、排坑技巧一次性聊透。
router-link和a标签核心区别是啥?
很多人初学的时候,会想“既然都是跳转链接,直接用a标签不行吗?”还真不行,得先搞懂前端路由的逻辑,Vue项目里用Vue Router做单页应用(SPA),页面切换是不刷新整个页面的,靠的是路由匹配组件渲染。
要是用普通a标签写<a href="/about">关于我们</a>
,点击后浏览器会直接发起请求,整个页面刷新,这就失去了SPA的优势,而router-link是Vue Router提供的声明式导航组件,它做了这些关键事儿:
- 自动适配路由模式:不管你用的是
hash
模式(URL带#,比如http://xxx/#/home
)还是history
模式(URL像普通网页,http://xxx/home
),router-link会自动生成对应的链接格式,不用你手动判断。 - 处理“激活状态”:当当前路由和router-link指向的路由匹配时,它会自动给元素加
active-class
(默认是router-link-active
),方便做选中样式,比如导航栏高亮,普通a标签得自己写JS判断路由来加样式,麻烦多了。 - 阻止默认跳转:点击router-link时,它内部会调用
router.push
(或replace等)方法,走前端路由逻辑,不会触发浏览器的页面刷新。
router-link最基础的用法有哪些?
先从最常用的to
属性说起,它决定了要跳转到哪个路由。
to属性的两种写法
- 字符串路径:适合简单的静态路由,比如路由配置里有
{ path: '/news', component: News }
,那router-link可以写:<router-link to="/news">新闻页</router-link>
- 对象语法:对付动态路由、命名路由更灵活,比如路由配置是
{ name: 'Article', path: '/article/:id', component: Article }
,用name匹配(避免路径硬编码),还能传参数:<router-link :to="{ name: 'Article', params: { id: 1001 }, // 动态路由参数 query: { tab: 'comment' } // 问号后的查询参数 }">查看文章</router-link>
这里
params
对应动态路由的idquery是查询参数,最终URL会变成
/article/1001?tab=comment`。
控制跳转行为的属性
- replace:默认点击router-link是用
router.push
(往历史记录栈里加一条),加了replace
后,会变成router.replace
(替换当前历史记录),比如从A页跳到B页,用replace的话,返回时会跳过A页,写法:<router-link to="/contact" replace>联系我们</router-link>
- tag:指定router-link渲染成什么HTML标签,默认是
<a>
标签,要是想改成按钮样式的<button>
,可以写<router-link to="/login" tag="button">登录</router-link>
,不过Vue Router 4之后更推荐用v-slot
自定义渲染,后面讲进阶的时候细说。
激活样式相关
默认情况下,当路由匹配时,router-link会加router-link-active
类名(全局配置里的activeClass
),如果想自定义类名,用active-class
属性:
<router-link to="/product" active-class="my-active">产品页</router-link>
但要注意精准匹配问题:比如你有/user
和/user/info
两个路由,点/user/info
时,/user
的router-link也会被激活(因为是包含匹配),这时候得用exact
属性或者exact-active-class
来做精准匹配:
<router-link to="/user" exact active-class="exact-active">用户主页</router-link>
加了exact
后,只有当路由完全等于/user
时才会激活这个link。
怎么给router-link加自定义样式?
导航栏选中态、不同页面的链接高亮,是前端常见需求,这里分两种情况:默认激活类名和自定义类名,还有Scoped样式下的处理。
用默认激活类名写样式
Vue Router默认给激活的router-link加router-link-active
类,精准匹配加router-link-exact-active
,所以可以直接写CSS:
.router-link-active { color: red; /* 选中时变红 */ border-bottom: 2px solid red; }
如果项目里用了CSS预处理器(比如Sass),嵌套写也没问题。
自定义active-class
前面讲过用active-class
指定类名,
<router-link to="/blog" active-class="blog-active">博客</router-link>
然后CSS里写:
.blog-active { /* 自己的样式逻辑 */ }
Scoped样式下的坑
Vue组件里<style scoped>
的样式是作用域隔离的,router-link渲染的元素可能不在当前组件作用域内(比如在App.vue里写的导航,被其他组件复用),这时候样式不生效,解决办法有两个:
- 去掉scoped,把导航样式放到全局CSS里(不太推荐,容易污染);
- 用深度选择器,比如Sass里的
>>>
或者::v-deep
:<style scoped> .nav-wrapper ::v-deep .blog-active { color: blue; } </style>
碰到router-link跳转没反应?先查这几点!
新手最头疼的就是“点了没反应”,得一步步排查:
路由配置是否匹配?
先看to
属性写的路径,和router/index.js
里的路由配置是否对应,比如路由配的是path: '/goods'
,你写to="/good"
(少了s),肯定匹配不上,如果用命名路由(name),得确保路由配置里有name: 'Goods'
这一项,否则对象语法里的name找不到对应路由。
动态路由参数传对了吗?
如果是动态路由(比如path: '/item/:id'
),用对象语法时params
必须传对应的id,否则路由解析会出错。
<!-- 错误:没传params.id --> <router-link :to="{ name: 'Item', params: {} }">商品</router-link> <!-- 正确 --> <router-link :to="{ name: 'Item', params: { id: 5 } }">商品</router-link>
路由模式是history时,后端配置了吗?
如果用history
模式(const router = new VueRouter({ mode: 'history' ... })
),部署到服务器后,直接访问http://xxx/about
会404,因为后端没配置 fallback,这时候需要后端把所有路由请求都转发到index.html
,让前端路由接管,如果没做这个配置,换成hash
模式临时测试下,看跳转是否正常。
是不是被组件缓存影响了?
如果页面用了<keep-alive>
缓存组件,路由跳转后组件没重新渲染,可能是因为activated
生命周期没处理好,或者路由参数变化时,组件的watch
没监听$route
,这时候得检查:
export default { watch: { $route(to, from) { // 路由变化时执行数据刷新逻辑 this.fetchData(to.params.id); } } }
进阶:router-link的v-slot怎么玩?
Vue Router 2.6+支持用v-slot
(插槽)来自定义router-link的渲染,灵活度拉满,比如不想渲染成a标签,想改成button,同时保留路由功能;或者给a标签加自定义属性。
基础插槽用法
router-link的默认插槽会暴露一些属性,比如href
(生成的链接)、navigate
(点击事件的处理函数),基本写法:
<router-link to="/cart" v-slot="{ href, navigate }" > <button :href="href" @click="navigate"> 购物车(自定义按钮) </button> </router-link>
这样点击按钮就会触发路由跳转,同时href也正确设置。
控制激活状态
插槽里还能拿到isActive
(是否匹配当前路由)、isExactActive
(是否精准匹配),用来自己控制样式:
<router-link to="/order" v-slot="{ isActive, navigate }" > <a @click="navigate" :class="{ 'order-active': isActive }" > 订单页 </a> </router-link> <style> .order-active { color: green; } </style>
结合Vue Router 4的变化
Vue Router 4里,router-link的插槽更强大,还能处理aria-current
等可访问性属性。
<router-link to="/help" v-slot="{ isActive, href, navigate }" > <a :href="href" @click="navigate" :aria-current="isActive ? 'page' : null" > 帮助中心 </a> </router-link>
这样对屏幕阅读器更友好,符合无障碍访问标准。
router-link的学习节奏
刚入门时,先把to
属性的两种写法、active-class
、replace
这些基础属性玩熟,能搞定大部分导航需求;碰到样式不生效、跳转失败,按照“路由配置→参数传递→模式兼容→组件缓存”的顺序排查;等对Vue Router有一定理解后,再去折腾v-slot
自定义渲染,实现更灵活的交互。
router-link是为了解决SPA导航的“无痛跳转 + 状态管理”问题,和传统a标签的区别本质是前端路由和后端路由的区别,把这些逻辑理顺,不管是写博客导航、电商页面跳转,还是复杂的后台管理系统菜单,都能游刃有余~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。