Vue Router的该怎么用?常见问题全解答
刚接触Vue Router的同学,肯定对
基础用法:怎么实现页面跳转?
Vue Router里的
最基础的用法是通过to属性指定目标路径:
- 字符串路径:直接写要跳转的路由地址,比如跳转到首页:
<router-link to="/home">首页</router-link>
- 对象形式:当需要传参、指定路由名称时更灵活,比如路由配置里给某个页面起了
name(如name: 'User'),可以这样写:<router-link :to="{ name: 'User', params: { id: 123 }, query: { tab: 'info' } }">用户页</router-link>这里
name对应路由的名称,params传动态参数,query传查询参数。
以前版本里还能通过tag属性指定tag属性被移除了,现在更推荐用v-slot来自定义渲染结构(后面进阶部分会讲),不过新手阶段先掌握to属性的基本用法,就能完成大部分跳转需求~
和普通标签有啥区别?
很多同学会疑惑:既然都是“链接”,为啥不用标签?这得从单页应用(SPA)的原理说起——
普通标签跳转时,浏览器会重新请求服务器,刷新整个页面,但Vue做的是单页应用,所有页面切换都该在“前端内部”完成(只更新页面里的组件,不刷新整个页面),这时候
- 无刷新跳转:
基于Vue Router的路由模式(history或hash)实现“前端路由”,点击时只会更新页面里的组件,不会触发全页面刷新,体验更流畅。 - 自动管理激活状态:当当前路由和
的 to路径匹配时,它会自动添加激活类(比如默认的router-link-active),方便做导航高亮,而标签得自己写JS判断路径来加类,麻烦多了。 - 传参更灵活:
的 to属性支持对象形式,能轻松传params(动态路由参数)、query(查询参数);标签只能手动拼接URL(比如<a href="/user?id=123">),不仅麻烦,还容易出错。
简单说:是“传统多页应用”的跳转方式,
用传参有哪些方式?
页面跳转时经常需要传数据(比如用户ID、筛选条件),
params传参(动态路由参数)
适合路径中需要包含参数的场景(比如用户详情页/user/123,123是用户ID),步骤分两步:
- 配置动态路由:在路由规则里用
“:参数名”定义,const routes = [ { path: '/user/:id', name: 'User', component: User } ] - 在
里传参 :用对象形式的to,通过params传值:<router-link :to="{ name: 'User', params: { id: 123 } }">用户123</router-link>这里必须用
name匹配路由(用path的话params会被忽略,这点要注意!)。
特点:参数会嵌入URL路径(比如/user/123),刷新页面时参数不会丢失(因为路由配置里有/:id,属于路由的一部分),但如果路由没配置动态参数,直接用params传参,刷新后参数会消失哦~
query传参(查询参数)
适合可选参数、筛选条件这类场景(比如列表页的搜索关键词、分页页码),用法更简单:
直接在to的对象里加query属性,
<router-link :to="{ path: '/about', query: { msg: 'hello', page: 2 } }">关于页</router-link>
跳转后URL会变成/about?msg=hello&page=2。
特点:参数在URL的后面,刷新页面时参数会保留(因为属于URL的一部分),但如果是敏感数据不适合用query(会暴露在URL里),用query传参时,to里用path或name都可以~
接收参数也很简单:在目标组件里通过this.$route.params.id(取params参数)或this.$route.query.msg(取query参数)就能拿到值~
如何给设置激活样式?
导航栏需要“当前页面高亮”是常见需求,
active-class:匹配时的激活类
当to路径和当前路由“部分匹配”时,会自动添加active-class指定的类,默认类名是router-link-active,也可以自己定义:
比如想把激活类改成my-active:
<router-link to="/home" active-class="my-active">首页</router-link>
然后在CSS里写.my-active的样式(比如改变文字颜色、加下划线)。
还能全局配置激活类:在创建路由实例时(createRouter),通过linkActiveClass选项统一设置,
const router = createRouter({
history: createWebHistory(),
routes,
linkActiveClass: 'global-active-class'
})
这样所有active-class都会变成global-active-class,不用每个组件重复写。
exact-active-class:精确匹配的激活类
有时候会遇到“路由嵌套”导致的激活问题,比如根路由是,子路由是/about,当跳转到/about时,的/about包含),这时候就需要精确匹配:
给exact属性,同时用exact-active-class指定精确匹配时的类:
<router-link to="/" exact exact-active-class="exact-active">首页</router-link>
这样只有当路径完全等于时,才会添加exact-active类,子路由跳转时就不会误激活啦~
嵌套路由里咋用?
很多项目有“父页面包含子页面”的结构(比如后台管理系统,左侧导航是父路由,右侧内容是子路由),这时候
先看路由配置的结构:
const routes = [
{
path: '/dashboard',
component: Dashboard,
children: [
{ path: 'analysis', component: Analysis }, // 子路由,路径是/dashboard/analysis
{ path: 'statistics', component: Statistics }
]
}
]
在父组件Dashboard的模板里,要跳转到子路由,
<template>
<div class="dashboard">
<router-link to="analysis">分析页</router-link>
<router-link to="statistics">统计页</router-link>
<router-view></router-view> <!-- 子路由组件渲染的地方 -->
</div>
</template>
这里的to="analysis"是相对路径,会自动拼接父路由的path(/dashboard),变成/dashboard/analysis,如果用绝对路径,得写to="/dashboard/analysis",但相对路径更灵活,父路由path变化时不用改子路由的link~
如果子路由的path是空字符串(比如children里{ path: '', component: Overview }),那跳转到父路由时会默认显示Overview组件,这时候<router-link to="" />就能跳转过去~
动态路由场景下怎么处理?
比如做“用户列表→用户详情”的功能,每个用户对应/user/:id,这时候需要循环渲染id。
假设用户数据是users数组,每个用户有id和name,写法可以是:
<template>
<div class="user-list">
<router-link
v-for="user in users"
:key="user.id"
:to="{ name: 'User', params: { id: user.id } }"
>{{ user.name }}</router-link>
</div>
</template>
这里要注意路由组件复用的问题:当从/user/1跳转到/user/2时,User组件的实例会被复用(因为路由路径变化但组件相同),这时候组件的created钩子不会重新执行,导致数据没更新,解决办法有两种:
- 监听
$route变化:在User组件里用watch监听$route:watch: { '$route' (to, from) { // 这里获取to.params.id,重新请求数据 } } - 使用
beforeRouteUpdate钩子:组件内定义beforeRouteUpdate(to, from, next) { // 处理参数变化,更新数据 next() }
所以动态路由场景下,
和编程式导航怎么配合?
Vue Router里除了this.$router.push()),两者各有适用场景,也能配合使用:
声明式 vs 编程式
配合使用的场景
比如有个“提交表单”按钮,点击后要先验证表单,再跳转,这时候可以用<button>,点击事件里写逻辑,再调用编程式导航:
<template>
<button @click="handleSubmit">提交</button>
</template>
<script>
export default {
methods: {
handleSubmit() {
if (this.formValid()) { // 验证表单
this.$router.push('/success') // 编程式导航跳转
}
}
}
}
</script>
但如果想保留@click.native.prevent,在事件里处理逻辑后再跳转:
<router-link to="/success" @click.native.prevent="handleSubmit">提交</router-link>
这里.native是监听原生点击事件,.prevent是阻止默认跳转(因为要自己控制什么时候跳),在handleSubmit里处理完逻辑后,再调用this.$router.push('/success')~
性能优化要注意啥?
如果项目里有大量
避免不必要的重渲染
结合路由懒加载
路由懒加载是指“访问该路由时才加载对应的组件代码”,配置方式是在路由规则里用() => import('./views/Home.vue')。
减少复杂计算在里
如果to属性绑定的是一个复杂的计算属性或方法,每次组件渲染都会重新计算,拖慢速度,可以把计算逻辑提前到data或computed里,再绑定给to:
<script>
export default {
computed: {
userPath() {
return { name: 'User', params: { id: this.userId } }
}
}
}
</script>
<template>
<router-link :to="userPath">用户页</router-link>
</template>
这样计算属性只会在依赖变化时重新计算,避免不必要的性能消耗~
到这里,
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网




发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。