Code前端首页关于Code前端联系我们

Vue Router的sub routes该怎么理解和使用?

terry 10小时前 阅读数 13 #Vue
文章标签 Vue Router;子路由

做前端项目时,你有没有遇到过这样的场景?比如后台管理系统里,点击左侧菜单后,右侧内容区要切换不同页面,但整个页面的头部、侧边栏又得保持不变,这时候 Vue Router 的 sub routes(子路由)就能帮上大忙,可子路由到底是什么?怎么配置?实战中要注意啥?今天咱们就把这些问题掰碎了聊聊。

sub routes 到底是什么?

简单说,sub routes 是嵌套在「父路由」里的路由规则,对应到页面结构上,就是一个页面里嵌套另一个(或多个)可切换的子页面。

举个直观的例子:假设做一个博客系统,有个「文章管理」页面,点击进入后,左侧是文章分类导航,右侧要根据点击的分类,显示「已发布文章列表」「草稿箱」「回收站」这几个不同的子页面,这时候,「文章管理」就是父路由,它下面的「已发布」「草稿箱」这些就是子路由,父路由对应的组件负责布局(比如左侧导航栏),子路由对应的组件负责填充右侧的具体内容。

从代码层面看,父路由的配置里会有一个 children 数组,里面装着所有子路由的规则;父路由对应的 Vue 组件里,得有 <router - view> 标签,用来渲染子路由对应的组件——这就像给子路由留了个“占位符”,子路由组件会替换这个占位符的内容。

为什么项目里需要用 sub routes?

很多同学会疑惑:直接用普通路由切换页面不行吗?为啥非得搞嵌套?这得从实际开发的场景和好处说起。

解决页面结构嵌套的需求

后台管理系统是最典型的场景,比如常见的“顶部导航 + 左侧菜单 + 右侧内容区”布局,右侧内容区需要根据左侧菜单切换不同页面,但顶部和左侧是固定不变的,这时候,把“顶部 + 左侧”所在的页面作为父路由,右侧内容区用子路由来切换,就能完美实现这种嵌套结构,要是不用子路由,每次切换页面都得重新渲染整个页面(包括顶部和左侧),不仅体验差,代码重复度也高。

让代码拆分和复用更合理

父路由组件可以专门负责“布局”逻辑(比如处理侧边栏的展开收起、权限控制),子路由组件只需要关注“内容展示”,这样分工明确,代码复用性更强,比如多个子路由可能都需要父路由里的用户信息、权限判断逻辑,父组件处理后,子组件直接用就行,不用重复写。

路由逻辑分层更清晰

子路由天然继承父路由的部分特性,比如父路由需要登录后才能访问,那子路由也会自动要求登录(除非单独配置权限),把相关功能的路由聚合在父路由下,路由表的结构会更清晰,比如电商系统里,“商品管理”作为父路由,下面的“商品列表”“新增商品”“编辑商品”作为子路由,看路由配置就能明白功能模块的层级关系,维护起来更方便。

怎么配置 Vue Router 的 sub routes?

配置子路由的核心是「父路由里加 children 数组 + 父组件里放 <router - view>」,下面一步步拆解。

准备父路由组件

先写一个负责布局的父组件,DashboardLayout.vue,里面得包含 <router - view> 来渲染子路由,示例代码:

```html ```

注意:<router - link>to 属性值,是相对于父路由的路径(后面讲路径配置时会详细说)。

配置路由规则里的 children

在 Vue Router 的路由数组中,给父路由对象加 children 数组,每个子路由对象包含 pathcomponent 等属性,示例路由配置:

```javascript import { createRouter, createWebHistory } from 'vue - router' import DashboardLayout from '@/components/DashboardLayout.vue' import DashboardHome from '@/views/dashboard/Home.vue' import Overview from '@/views/dashboard/Overview.vue' import Analytics from '@/views/dashboard/Analytics.vue'

const routes = [ { path: '/dashboard', // 父路由的路径 component: DashboardLayout, // 父路由对应的组件 children: [ { path: '', // 默认子路由,访问 /dashboard 时渲染这个 name: 'DashboardHome', component: DashboardHome }, { path: 'overview', // 子路由路径,完整路径是 /dashboard/overview component: Overview }, { path: 'analytics', // 完整路径 /dashboard/analytics component: Analytics } ] } ]

const router = createRouter({ history: createWebHistory(), routes })

export default router

<p>这里要注意几个关键点:</p>
<ul>
  <li><strong>子路由的 path 不带 /</strong>:比如子路由写 <code>path: 'overview'</code>,那么完整路径是父路由的 <code>path</code>(/dashboard) + 子路由的 <code>path</code>(overview),即 <code>/dashboard/overview</code>,如果子路由写 <code>path: '/overview'</code>,完整路径会变成 <code>/overview</code>,就脱离父路由了,这是常见错误!</li>
  <li><strong>默认子路由</strong>:当子路由的 <code>path</code> 为空字符串时,访问父路由的路径(如 /dashboard)时,会默认渲染这个子路由对应的组件(上面例子里的 DashboardHome)。</li>
  <li><strong>父组件必须有 &lt;router - view&gt;</strong>:如果父组件里没写 <code>&lt;router - view&gt;</code>,子路由组件没地方渲染,页面会一片空白,这也是新手常踩的坑。</li>
</ul>
## 四、实战中怎么结合组件结构用 sub routes?
<p>光看配置还不够,得结合真实项目结构理解,咱们以“后台管理系统的仪表盘模块”为例,完整走一遍流程。</p>
### 1. 规划项目文件结构
<p>假设项目的组件和视图结构如下:</p>

src/ ├── components/ │ └── layouts/ │ └── DashboardLayout.vue // 父路由组件(负责布局) ├── views/ │ └── dashboard/ │ ├── Home.vue // 仪表盘默认子页面 │ ├── Overview.vue // 概览子页面 │ └── Analytics.vue // 分析子页面 └── router/ └── index.js // 路由配置文件


### 2. 写父组件(DashboardLayout.vue)的布局逻辑
<p>父组件要包含侧边栏导航和 <code>&lt;router - view&gt;</code>,示例:</p>
```html
<template>
  <div class="dashboard-layout">
    <aside class="sidebar">
      <h2>仪表盘</h2>
      <nav>
        <router - link to="">首页</router - link>
        <router - link to="overview">概览</router - link>
        <router - link to="analytics">分析</router - link>
      </nav>
    </aside>
    <main class="content">
      <router - view></router - view>
    </main>
  </div>
</template>
<script setup>
// 可以在这里处理侧边栏的展开/收起、权限判断等逻辑
import { onMounted } from 'vue'
onMounted(() => {
  console.log('父组件加载,子路由还没渲染')
})
</script>
<style scoped>
.dashboard-layout {
  display: flex;
}
.sidebar {
  width: 200px;
  background: #f5f7fa;
  padding: 20px;
}
.content {
  flex: 1;
  padding: 20px;
}
</style>

写子组件(以 Overview.vue 为例)

子组件只需要关注自己的内容展示,

```html ```

测试路由跳转

启动项目后,访问 /dashboard,会看到侧边栏和默认子组件(Home.vue)的内容;点击“概览”的 router - link,地址栏变成 /dashboard/overview区切换为 Overview.vue 的内容——这就说明子路由配置成功了。

还可以给子路由加动态参数,比如商品编辑页面:

```javascript // 路由配置里加动态子路由 children: [ { path: 'edit/:id', // 动态参数 id component: ProductEdit } ]

// ProductEdit 组件里获取参数 import { useRoute } from 'vue - router' const route = useRoute() const productId = route.params.id // 拿到路由参数

<p>这种动态子路由在“编辑详情”类场景中特别常用,父组件负责列表和布局,子路由负责具体的编辑页面,参数通过路由传递,逻辑更清晰。</p>
## 五、sub routes 容易踩的坑有哪些?
<p>子路由配置看起来简单,但实际开发中稍不注意就会出问题,总结几个高频“踩坑点”,帮你避坑。</p>
### 1. 父组件忘记加 &lt;router - view&gt;
<p><strong>现象</strong>:访问子路由时,父组件的布局能显示,但子组件内容空白。<br>
<strong>原因</strong>:子路由组件需要渲染到父组件的 <code>&lt;router - view&gt;</code> 里,如果父组件没写这个标签,子组件没地方渲染。<br>
<strong>解决</strong>:检查父组件模板,确保有 <code>&lt;router - view&gt;&lt;/router - view&gt;</code> 标签。</p>
### 2. 子路由 path 多写了 /
<p><strong>现象</strong>:点击子路由的 <code>router - link</code> 后,地址栏路径不对,页面404。<br>
<strong>原因</strong>:子路由的 <code>path</code> 开头加了 <code>/</code>,导致路径变成绝对路径,脱离父路由,比如父路由是 <code>/dashboard</code>,子路由写 <code>path: '/overview'</code>,完整路径会变成 <code>/overview</code>,而不是 <code>/dashboard/overview</code>。<br>
<strong>解决</strong>:子路由的 <code>path</code> 不要以 <code>/</code> 开头,保持相对路径。</p>
### 3. 默认子路由的导航链接问题
<p><strong>现象</strong>:访问父路由(如 <code>/dashboard</code>)时,默认子路由组件能渲染,但 <code>router - link</code> 的“首页”链接样式没激活(active - class 不生效)。<br>
<strong>原因</strong>:默认子路由的 <code>path</code> 是空字符串,<code>router - link</code> 的 <code>to</code> 属性写 <code>to=""</code> 时,匹配的是父路由路径,而默认子路由的 <code>path</code> 是空,所以需要给默认子路由加 <code>name</code>,<code>router - link</code> 用 <code>to="{ name: 'DashboardHome' }"</code> 来匹配。<br>
<strong>解决</strong>:给默认子路由配置 <code>name</code>,并在 <code>router - link</code> 中用命名路由跳转,示例:</p>
```javascript
// 路由配置
children: [
  { 
    path: '', 
    name: 'DashboardHome', // 加 name
    component: DashboardHome 
  }
]
// 父组件的 router - link
<router - link :to="{ name: 'DashboardHome' }">首页</router - link>

路由嵌套层级过深

现象:路由表变得臃肿,页面跳转逻辑复杂,维护困难。
原因:为了实现复杂布局,过度使用子路由嵌套(比如嵌套三层以上)。
解决:合理规划路由结构,把没必要嵌套的路由拆分成平级路由,或用命名视图替代深层嵌套,比如页面有多个并行区域(如头部、侧边、内容),用命名视图更合适,不用嵌套子路由。

子路由守卫和父路由守卫的执行顺序

现象:在子路由里用 beforeEnter 守卫,或在父组件里用 beforeRouteUpdate,发现逻辑执行顺序和预期不一致。
原因:Vue Router 的导航守卫有固定的执行顺序(比如父路由的 beforeEnter 先于子路由的 beforeEnter 执行,子路由的 beforeRouteEnter 在组件创建前执行等),没理解清楚容易出错。
解决:查阅 Vue Router 官方文档,明确守卫的执行顺序,必要时通过 console.log 打印日志调试。

sub routes 和动态路由、命名视图有什么区别?

学子路由时,很容易和动态路由、命名视图搞混,得明确它们的区别。

和动态路由的区别

动态路由的核心是「路由参数」,/user/:id,同一个组件(User.vue)根据不同的 id 显示不同用户的信息,组件会复用(不会销毁重建),而子路由的核心是「结构嵌套」,父组件负责布局,子组件负责不同内容的切换,组件是不同的。

举例子:动态路由适合“用户详情”“商品详情”这类场景(同一个页面模板,数据不同);子路由适合“仪表盘 - 概览/分析”这类嵌套布局场景(不同页面模板,结构嵌套)。

和命名视图的区别

命名视图是给 <router - view>name 属性,一个页面里可以有多个 <router - view name="xxx">,分别渲染不同的组件,比如一个页面要同时渲染「头部组件」「侧边栏组件」「主体组件」,这三个组件通过命名视图并行渲染。

而子路由是「嵌套渲染」——父组件里的 <router - view> 渲染子组件,子组件里还能再嵌套 <router - view> 渲染孙子路由,是层级关系。

举例子:命名视图适合“多区域并行渲染”(如门户首页的头部、轮播、推荐区);子路由适合“单区域嵌套渲染”(如后台管理系统的内容区嵌套子页面)。

在 Vue3 和 Vue2 中 sub routes 的使用有变化吗?

Vue2 和 Vue3 都支持子路由,但由于生态和 API 的变化,使用时也有一些细节差异。

路由配置方式

Vue2 中,路由通过 VueRouter 构造函数创建,示例:

```javascript import Vue from 'vue' import Router from 'vue - router' Vue.use(Router)

const router = new Router({ routes: [ { path: '/dashboard', component

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

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

热门