一、vue-router子路由到底是什么?
刚接触vue-router的同学,经常会疑惑「子路由是啥?配置和使用时有啥要注意的?碰到不显示、传参失败这些问题咋解决?」今天就用问答形式把vue-router子路由的核心知识、实操方法、避坑技巧一次性讲明白,新手也能轻松看懂~
子路由是**路由的“嵌套结构”**——父路由对应的组件里得有个`打个比方:做后台管理系统时,肯定有个“整体布局组件”(比如叫Layout),里面包含侧边栏、顶部导航栏,中间留一块区域放不同页面(比如用户列表、订单列表),这时候,“用户列表”“订单列表”这些路由就是Layout的子路由,它们的组件会被塞进Layout里的<router-view>位置。
子路由的核心作用是实现页面嵌套布局,让代码结构像“俄罗斯套娃”一样一层包一层,既符合SPA(单页应用)的组件化思想,又能让用户切换子页面时,外层布局(比如侧边栏)保持不变,体验更流畅。
怎么给项目配置子路由?分步骤讲
配置子路由像“搭积木”,得先准备好带<router-view>的父组件,再给路由规则加“子规则”,下面一步步拆:
步骤1:准备父路由组件
先写负责“外层布局”的父组件(比如叫Layout.vue),里面必须包含<router-view>(这是子路由组件的“挂载点”),举个简单结构:
<template>
<div class="layout">
<aside>侧边栏</aside>
<main>
<!-- 子路由组件会渲染到这里 -->
<router-view></router-view>
</main>
</div>
</template>
步骤2:在路由配置里加children数组
打开路由配置文件(比如router/index.js),给父路由对象加children属性(数组类型),每个数组元素是子路由规则,注意这些细节:
- 子路由的
path不用加斜杠(比如父路由path是/dashboard,子路由path写analysis,完整路径就是/dashboard/analysis;加斜杠会变成根路径下的路由,脱离父路由)。 - 每个子路由得配
component(要渲染的组件),用懒加载(() => import('./views/xxx.vue'))更高效。
举个完整配置例子:
import { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/views/Layout.vue'
const routes = [
{
path: '/dashboard', // 父路由路径
component: Layout, // 父路由组件
children: [
{
path: 'analysis', // 子路由路径,完整路径/dashboard/analysis
component: () => import('@/views/DashboardAnalysis.vue') // 子组件(懒加载)
},
{
path: 'workbench',
component: () => import('@/views/DashboardWorkbench.vue')
}
]
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
步骤3:用<router-link>或编程式导航跳转
配置好后,跳转子路由有两种方式:
- 声明式导航:用
<router-link>标签,比如跳转到analysis子路由:<router-link to="/dashboard/analysis">分析页</router-link>
- 编程式导航:在方法里用
this.$router.push('/dashboard/analysis')(Vue2)或useRouter().push('/dashboard/analysis')(Vue3)。
踩坑提醒:如果子路由没渲染,先检查父组件有没有<router-view>,以及子路由的path和父路由的path是否“拼接”正确~
子路由有哪些实用场景?
子路由不止“嵌套”这么简单,实际项目里能解决很多布局和交互问题,举几个高频场景:
场景1:后台管理系统的“布局复用”
后台系统常见结构是「侧边栏+顶部栏+内容区」,把侧边栏和顶部栏放到Layout组件里,内容区用<router-view>,用户、订单、商品等模块作为子路由,切换时只有内容区刷新,侧边栏和顶部栏不动,既减少重复代码,又让用户操作更流畅。
场景2:页面内的Tab切换
比如商品详情页有「基本信息」「用户评价」「推荐商品」三个Tab,给每个Tab配个子路由,点击Tab时切换子路由,不仅能让路由记录当前Tab状态(刷新页面也能回到当前Tab),还能通过路由传参(比如商品ID)让每个Tab组件更独立。
场景3:多级导航的“层级嵌套”
像电商平台的分类页:一级分类(数码”)是父路由,二级分类(手机”)是子路由,三级分类(苹果手机”)是子路由的子路由(孙子路由),每层路由对应不同组件,用<router-view>一层套一层,完美实现多层级页面结构。
子路由常见问题怎么解决?
配置和使用时,最容易碰到“子组件不显示”“传参失败”这些坑,下面逐个拆解解决方案:
问题1:子路由组件死活不显示?
先做这几步排查:
- 检查父路由组件里有没有
<router-view>,没写这个标签,子组件根本没地方渲染! - 检查子路由的
path是否正确,比如父路由path是/dashboard,子路由path写成/dashboard/analysis(多写了父路径),会导致路径不匹配。 - 检查路由配置语法,比如
children数组是不是放在父路由对象里?有没有少写逗号、括号?(新手容易犯这种错) - 检查子组件是否正确导入,比如懒加载时路径写错导致404,或组件没
export default导致“组件未定义”。
问题2:子路由怎么传参?三种方法任选
子路由和父路由传参逻辑和普通路由一致,但要注意“路径层级”,推荐这三种方法:
-
动态路由传参:子路由
path写动态参数(比如path: 'detail/:id'),跳转时用/dashboard/detail/123,子组件通过this.$route.params.id(Vue2)或useRoute().params.id(Vue3)获取。 -
查询参数(query):跳转时带
?name=xxx(比如<router-link to="/dashboard/detail?name=手机">),子组件用this.$route.query.name拿值,好处是参数可见,刷新页面参数不丢。 -
props传参(推荐解耦写法):在子路由配置里开
props: true,子组件用props接收,例子:// 路由配置 { path: 'detail/:id', component: ProductDetail, props: true } // 子组件ProductDetail.vue export default { props: ['id'], mounted() { console.log(this.id) // 直接用props,不用依赖$route,更解耦 } }
问题3:子路由的导航守卫咋用?
导航守卫能控制“能不能进入子路由”,常用这两种场景:
- 子路由独享守卫
beforeEnter:写在子路由配置里,进入子路由前判断权限。{ path: 'analysis', component: DashboardAnalysis, beforeEnter: (to, from, next) => { if (localStorage.getItem('token')) { // 假设用token判断权限 next() // 有权限,进入子路由 } else { next('/login') // 没权限,跳登录页 } } } - 父组件的
beforeRouteUpdate:子路由切换但父组件被复用(比如动态路由参数变化)时,这个钩子会触发,比如父路由是/user/:id,从/user/1跳到/user/2,父组件复用,这时可在beforeRouteUpdate里更新数据:export default { beforeRouteUpdate(to, from, next) { this.fetchData(to.params.id) // 根据新的id重新请求数据 next() } }
问题4:子路由和动态路由有啥区别?
很多同学会混淆这两个概念,简单总结:
- 动态路由:核心是“路径带参数”(比如
/user/:id),用来匹配不同ID的用户页面,重点在“参数匹配”。 - 子路由:核心是“嵌套结构”,用来实现页面的层级布局,重点在“组件嵌套”。
- 关系:动态路由可以是子路由的一部分,比如父路由是
/user,子路由是/user/:id/profile,这时子路由同时也是动态路由。
子路由进阶:多层嵌套与性能优化
项目复杂时,子路由可能要嵌套“孙子路由”,甚至做性能优化,掌握后能让项目更丝滑~
多层嵌套:子路由里再套子路由
做“三层嵌套”页面(A组件→B组件→C组件)时,配置要在子路由的children里再放children:
{
path: '/a',
component: A,
children: [
{
path: 'b',
component: B,
children: [
{
path: 'c',
component: C
}
]
}
]
}
这时,A组件里的<router-view>渲染B组件,B组件里的<router-view>渲染C组件。注意:每一层嵌套都得有<router-view>,否则下一层组件没地方渲染!
性能优化:懒加载+keep-alive
子路由多的话,全塞进首屏加载会很慢,用懒加载(把component写成() => import('xxx.vue'))能让首屏只加载必要组件,其他子路由等需要时再加载,减少初始包体积。
用keep-alive缓存子路由组件实例,避免重复渲染,在父组件的<router-view>外层包keep-alive:
<template>
<div class="layout">
<aside>侧边栏</aside>
<main>
<keep-alive>
<router-view></router-view>
</keep-alive>
</main>
</div>
</template>
但keep-alive会缓存组件状态,若子组件需“每次进入都刷新数据”,得用activated和deactivated钩子:
export default {
activated() {
this.fetchData() // 每次激活组件(进入子路由)时请求数据
},
deactivated() {
// 离开时的逻辑,比如清空定时器
}
}
到这里,vue-router子路由的核心知识、配置方法、避坑技巧、进阶玩法就讲透啦~记住核心逻辑:子路由是嵌套结构,靠父组件的<router-view>挂载,配置时用children数组,使用时注意路径和传参细节,多在项目里实操几次,自然就熟练啦~如果还有其他问题,评论区随时喊我~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网




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