一、Router Link和普通a标签有啥不一样?
做Vue项目时,页面跳转离不开Router Link,但很多同学刚接触时一头雾水:它和普通a标签区别是啥?动态路由咋传参?激活样式咋调?遇到跳转没反应该咋排查?这篇文章把Router Link从基础用法到实战踩坑全拆清楚,新手能快速上手,老手也能补漏~
先搞懂“表面”和“内核”的区别:普通a标签是浏览器原生组件,点击后会整页刷新(比如从localhost:8080/page1跳到/page2,浏览器会重新请求服务器);而Router Link是Vue Router提供的前端路由组件,专门给单页应用(SPA)用的,点击后不会刷新页面,而是通过修改URL、匹配路由规则,渲染对应的组件(靠router-view实现)。
再看“内部渲染”:Router Link最终也会被渲染成a标签,但多了一堆路由逻辑,比如点击时会阻止a标签默认的跳转行为(不然又整页刷新了),还会自动处理“当前路由是否激活”的样式(activeClass),举个简单对比:
<!-- 普通a标签,整页刷新 --> <a href="/about">关于我们</a> <!-- Router Link,单页无刷新跳转 --> <router-link to="/about">关于我们</router-link>
Router Link的to属性支持对象语法(传路由name、params、query),灵活性远超a标签的href,比如要传动态参数:
<router-link :to="{ name: 'user', params: { id: 123 }}">用户123</router-link>
Router Link基础用法:这些细节别踩坑
刚用Router Link时,最容易栽在to属性、特殊属性(replace、tag)这些细节上,逐个拆解:
to属性的两种写法
to属性负责指定“跳转到哪”,有静态字符串和动态对象两种写法:
- 静态字符串:适合固定路径,比如
,直接写死路径。联系我们 - 动态对象:适合传参数、匹配路由
name(比路径更稳定,路径改了name能不变),格式是{ name: '路由名', params: { 动态参数 }, query: { 查询参数 } },比如路由配置里有{ name: 'article', path: '/article/:id' },那传参可以写:
<router-link :to="{
name: 'article',
params: { id: articleId }, // 对应动态路由/:id
query: { tab: 'comment' } // 对应?tab=comment
}">文章详情</router-link>
这里要注意:params传的是动态路由参数(路径里的/:id),刷新页面后会丢失;query传的是查询参数(后面的),刷新不会丢,根据需求选传参方式~
replace属性:控制历史记录
默认情况下,点击Router Link会往浏览器历史记录里新增一条(比如从/page1到/page2,返回能回到page1),加了replace后,会替换当前历史记录(返回时跳过当前页),场景:比如支付成功页,希望用户返回时直接回到订单列表,不用经过支付页,就可以加replace:
<router-link to="/pay/success" replace>支付成功</router-link>
tag属性:把Router Link渲染成其他标签
默认Router Link渲染成a标签,但有时候需要渲染成
<router-link to="/home" tag="li">首页</router-link> <!-- 渲染后是<li>首页</li>,但依然有路由跳转功能 -->
动态路由场景:Router Link咋传参才对?
做项目时,“用户详情页”“文章详情页”这类动态路由很常见,Router Link传参得注意匹配路由配置,分两步:
先配好动态路由规则
在router/index.js里,给路由加动态参数(用占位):
const routes = [
{
name: 'user',
path: '/user/:id', // :id是动态参数
component: User
}
]
Router Link传参的两种姿势
传参要和路由规则对应,不然会跳转到404或者参数丢失。
- 用
params传动态路由参数:必须配合路由的name(用path也能传,但name更可靠),比如用户ID是123,传参:
<router-link :to="{ name: 'user', params: { id: 123 }}">用户123</router-link>
<!-- 匹配后的路径是/user/123 -->
如果用path传params,虽然能跳转,但params会被忽略(这是Vue Router的设计,避免路径和参数不匹配),所以优先用name + params。
- 用
query传查询参数:适合非路径必须的参数(比如分页、筛选),格式是?key=value,比如传页码:
<router-link :to="{ name: 'articleList', query: { page: 2 }}">第2页</router-link>
<!-- 匹配后的路径是/articleList?page=2 -->
query传参刷新页面不会丢,因为参数在URL里;而params传参如果没配到动态路由里,刷新就没了(比如路由没写:id,却用params传id,刷新后id会消失),所以传参前一定先看路由配置里有没有对应的动态参数~
激活样式咋精准控制?解决“高亮不对”难题
导航栏点击后要高亮当前页,这是Router Link的核心需求,但新手常遇到“点击子路由,父路由也高亮”“样式死活不生效”这些问题,关键在activeClass和exactActiveClass。
默认激活样式:router-link-active和router-link-exact-active
Vue Router默认给激活的Router Link加两个类:
router-link-active:只要当前路由包含目标路由就会加(比如路由是/user/123,目标路由是/user,也会激活)。router-link-exact-active:只有完全匹配目标路由才会加(路由是/user/123,目标路由是/user,不会激活;只有路由是/user时才会激活)。
举个场景:导航栏有“首页()”和“用户(/user)”,点击“用户”进入/user/123,这时候“首页”的Router Link因为是,会被router-link-active激活(因为/user/123包含),导致首页也高亮——这明显不对!这时候就要用exact解决。
用exact解决“父路由被误激活”
给Router Link加exact属性,让它只在完全匹配时激活:
<router-link to="/" exact>首页</router-link> <router-link to="/user">用户</router-link>
这样点击/user/123时,“首页”的Router Link因为加了exact,只有路由是时才会激活,就不会误高亮了。
自定义激活类名
默认类名不够用?可以全局或局部自定义:
- 全局配置:在创建路由实例时,用
linkActiveClass和linkExactActiveClass指定:
const router = createRouter({
history: createWebHistory(),
routes,
linkActiveClass: 'my-active', // 替代router-link-active
linkExactActiveClass: 'my-exact-active' // 替代router-link-exact-active
})
- 局部配置:单个Router Link组件里用
active-class和exact-active-class:
<router-link to="/" exact active-class="nav-active" exact-active-class="nav-exact-active" >首页</router-link>
这样就能用自己的类名控制高亮样式,配合CSS写hover、active状态更灵活~
Router Link和导航守卫咋配合?权限控制、页面拦截全靠它
导航守卫(比如beforeEach、beforeRouteEnter)是控制路由权限、处理加载状态的关键,Router Link的跳转也会触发这些守卫,举几个实用场景:
全局守卫:判断用户是否登录
比如点击“订单列表”(需要登录),Router Link触发跳转,全局守卫beforeEach拦截:
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isLogin()) {
next('/login') // 没登录,跳转到登录页
} else {
next() // 放行
}
})
路由配置里给需要权限的路由加meta:
{
path: '/order',
component: Order,
meta: { requiresAuth: true }
}
这样点击时,就会触发beforeEach,检查登录状态。
组件内守卫:离开页面时确认
比如编辑页面,用户输入内容没保存,点击Router Link跳转时,用beforeRouteLeave提示:
export default {
data() {
return { formEdited: false }
},
beforeRouteLeave(to, from, next) {
if (this.formEdited) {
if (window.confirm('内容没保存,确定离开?')) {
next()
} else {
next(false) // 取消跳转
}
} else {
next()
}
}
}
这时候点击其他Router Link(比如跳转到首页),就会触发这个守卫,实现“离开前确认”。
嵌套路由里,Router Link咋处理多层跳转?
做后台管理系统时,经常遇到“父菜单→子菜单”的嵌套路由(比如/home → /home/about),Router Link在嵌套场景下要注意路径匹配和相对路由。
先配好嵌套路由
在router/index.js里,用children数组配置子路由:
const routes = [
{
path: '/home',
component: Home,
children: [
{
path: 'about', // 注意:这里没加/,是相对父路由/home的路径
component: HomeAbout
}
]
}
]
嵌套路由下的Router Link
在Home组件里,跳转到子路由about,Router Link的to可以用相对路径:
<template>
<div>
<!-- 父组件Home里的子路由跳转 -->
<router-link to="about">关于Home</router-link>
<!-- 渲染后的路径是/home/about -->
</div>
</template>
如果写绝对路径/to/about,就会匹配到根路由下的about(如果有的话),容易导致404,所以嵌套路由里,优先用相对路径,或者用路由name(更保险)。
父路由和子路由的Router Link激活样式也要注意,比如父路由是/home,子路由是/home/about,点击子路由时,父路由的Router Link也会被激活(因为包含/home),这时候给父路由的Router Link加exact吗?不行,因为父路由的路径是/home,子路由是/home/about,父路由的Router Link的to是/home,所以当路由是/home/about时,父路由的Router Link的activeClass是否激活?因为/home/about包含/home,所以父路由的Router Link会被加上router-link-active类,这时候如果希望父路由只有在精确匹配/home时才激活,子路由激活时父路由不激活,就要给父路由的Router Link加exact:
<router-link to="/home" exact>Home</router-link>
这样点击子路由/home/about时,父路由的Router Link因为加了exact,只有路由是/home时才激活,子路由激活时父路由就不会高亮了。
Router Link跳转没反应?五步排坑法
遇到“点击Router Link没反应,页面也不跳转”,别慌,按这几步排查:
检查路由配置
看目标路由的path、name、component是否配置正确,比如路由配置里写的是path: '/contactus',但Router Link的to是'/contact',路径不匹配就跳不动。
检查to属性绑定
动态绑定to时,有没有加(v-bind)?
<!-- 错误:to是字符串,不是动态绑定,params传不进去 -->
<router-link to="{ name: 'user', params: { id: 123 }}">用户</router-link>
<!-- 正确:加:,动态绑定对象 -->
<router-link :to="{ name: 'user', params: { id: 123 }}">用户</router-link>
检查路由模式和后端配置
如果用 本文仅代表作者观点,不代表Code前端网立场。history模式,后端必须配置 版权声明
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网


