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

一、vue-router子路由到底是什么?

terry 3周前 (09-07) 阅读数 45 #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,子路由pathanalysis,完整路径就是/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:子路由组件死活不显示?

先做这几步排查:

  1. 检查父路由组件里有没有<router-view>,没写这个标签,子组件根本没地方渲染!
  2. 检查子路由的path是否正确,比如父路由path/dashboard,子路由path写成/dashboard/analysis(多写了父路径),会导致路径不匹配。
  3. 检查路由配置语法,比如children数组是不是放在父路由对象里?有没有少写逗号、括号?(新手容易犯这种错)
  4. 检查子组件是否正确导入,比如懒加载时路径写错导致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会缓存组件状态,若子组件需“每次进入都刷新数据”,得用activateddeactivated钩子:

export default {
  activated() {
    this.fetchData() // 每次激活组件(进入子路由)时请求数据
  },
  deactivated() {
    // 离开时的逻辑,比如清空定时器
  }
}

到这里,vue-router子路由的核心知识、配置方法、避坑技巧、进阶玩法就讲透啦~记住核心逻辑:子路由是嵌套结构,靠父组件的<router-view>挂载,配置时用children数组,使用时注意路径和传参细节,多在项目里实操几次,自然就熟练啦~如果还有其他问题,评论区随时喊我~

版权声明

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

发表评论:

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

热门