Vue3 零基础每日笔记(048):嵌套路由与命名视图——后台管理系统布局雏形

一、前言

后台管理系统的标准长相:顶栏 + 侧边菜单 + 内容区,点菜单只有内容区变 ,顶栏侧栏纹丝不动。这就是嵌套路由的战场:路由里套路由,页面里套页面。本篇用 children 配置搭出后台布局雏形,顺带认识命名视图。

二、嵌套路由:路由里套路由

场景:/admin 下的"个人资料"和"系统设置"两个子页面,共享一个后台布局。

ts 复制代码
// src/router/index.ts
import AdminLayout from '@/views/AdminLayout.vue'

const routes = [
  {
    path: '/admin',
    component: AdminLayout,          // 父路由:布局页
    children: [                      // ★ 子路由数组
      {
        // 注意:子路由 path 不以 / 开头(相对父路径)
        path: 'profile',
        name: 'admin-profile',
        component: () => import('@/views/admin/ProfileView.vue')
      },
      {
        path: 'settings',
        name: 'admin-settings',
        component: () => import('@/views/admin/SettingsView.vue')
      }
    ]
  }
]

父组件 AdminLayout 里挖第二个出口:

vue 复制代码
<!-- src/views/AdminLayout.vue -->
<template>
  <div class="admin">
    <aside class="side">
      <h3>后台管理</h3>
      <!-- 子路由链接:to 写完整路径 -->
      <RouterLink to="/admin/profile">个人资料</RouterLink>
      <RouterLink to="/admin/settings">系统设置</RouterLink>
    </aside>

    <main class="content">
      <!-- 二号出口:子路由组件渲染在这里 -->
      <RouterView />
    </main>
  </div>
</template>

<style scoped>
.admin { display: flex; min-height: 200px; border: 1px solid #eee; }
.side { width: 140px; background: #f5f5f5; padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.content { flex: 1; padding: 16px; }
</style>

结构一层套一层:URL /admin/profile 匹配 AdminLayout → 其内部 RouterView 再渲染 ProfileView。子路由的出口永远在父组件的 RouterView 里 ------访问 /admin/profile 时 App.vue 的出口渲染 AdminLayout,AdminLayout 的出口渲染 ProfileView,两层同时渲染。

【截图位置:点击侧边菜单只有内容区变化的效果】

三、两个必会细节:默认子路由与"不写 /"

1. 子路由 path 不以 / 开头 :path: 'profile' 相对拼接成 /admin/profile。写了 /profile 会变成顶级路由 /profile(脱离父布局)------子路由斜杠必须省,这是新人第一大坑。

2. 默认子路由 :访问 /admin(不带子路径)时显示什么?给 children 加一条空 path 的子路由:

ts 复制代码
children: [
  {
    path: '',                    // 空字符串 = 默认子路由
    redirect: { name: 'admin-profile' }   // 方案 A:重定向到 profile
  },
  {
    path: 'profile',
    name: 'admin-profile',
    component: () => import('@/views/admin/ProfileView.vue')
  },
  // ...
]

或者直接给空 path 配组件(/admin 本身就渲染 profile 内容):

ts 复制代码
{
  path: '',                       // 方案 B:/admin 直接渲染默认页
  name: 'admin-home',
  component: () => import('@/views/admin/ProfileView.vue')
}

方案 A(redirect)语义更清晰,企业里常用。

四、多级嵌套:children 里还有 children

ts 复制代码
{
  path: '/admin',
  component: AdminLayout,
  children: [
    {
      path: 'settings',
      component: () => import('@/views/admin/SettingsView.vue'),
      children: [
        { path: 'basic', component: () => import('@/views/admin/SettingsBasic.vue') },
        { path: 'safe', component: () => import('@/views/admin/SettingsSafe.vue') }
      ]
    }
  ]
}

SettingsView 里再放一个 RouterView 渲染 basic/safe。三层结构 = 三个 RouterView 同时渲染。嵌套别超过三四层(024 篇套娃警告在路由里同样生效),太深说明信息架构有问题。

五、命名视图:一个页面多个出口

嵌套路由是"父子关系",命名视图是"兄弟并排"------同一层挖几个坑,按名字填:

ts 复制代码
// 同一个 path,配多个组件
{
  path: '/dashboard',
  components: {                   // ★ 注意 components 复数
    default: () => import('@/views/dash/MainView.vue'),   // 无名出口
    sidebar: () => import('@/views/dash/SideView.vue'),   // 名叫 sidebar 的出口
    header: () => import('@/views/dash/HeaderView.vue')   // 名叫 header 的出口
  }
}
vue 复制代码
<!-- 模板里按名字认领 -->
<template>
  <RouterView name="header" />
  <div class="row">
    <RouterView name="sidebar" />
    <RouterView />   <!-- 不写 name = default -->
  </div>
</template>

使用频率不高(布局通常一个出口够用),但 el-container 布局 + 多区域路由的场景会遇到,认识即可。

六、综合实战:后台布局雏形(完整代码)

把默认子路由 + 侧边菜单 + 内容区整合成可运行版本:

ts 复制代码
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import AdminLayout from '@/views/AdminLayout.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    { path: '/', name: 'home', component: () => import('@/views/HomeView.vue') },
    {
      path: '/admin',
      component: AdminLayout,
      children: [
        { path: '', redirect: { name: 'admin-profile' } },
        {
          path: 'profile',
          name: 'admin-profile',
          component: () => import('@/views/admin/ProfileView.vue')
        },
        {
          path: 'settings',
          name: 'admin-settings',
          component: () => import('@/views/admin/SettingsView.vue')
        }
      ]
    }
  ]
})

export default router
vue 复制代码
<!-- src/views/admin/ProfileView.vue -->
<template><h4>👤 个人资料页</h4><p>只有内容区在变</p></template>
vue 复制代码
<!-- src/views/admin/SettingsView.vue -->
<template><h4>⚙️ 系统设置页</h4><p>顶栏侧栏毫无反应</p></template>

AdminLayout 用第四节那份(含样式)。跑起来:/admin 自动重定向到 profile,点菜单切换子页面,布局层稳如泰山------这就是 068 篇后台骨架的地基。

【截图位置:/admin 默认进入 profile、切换 settings 的运行效果】

七、踩坑记录

  1. 子路由 path 带了 / :path: '/profile' 变成顶级路由,脱离父布局,访问 /admin/profile 匹配不到------子路由一律省斜杠
  2. 忘了在父组件放 RouterView:子路由匹配成功但页面只显示布局、内容空白------父组件没挖坑
  3. RouterLink 的 to 写了相对路径 :<RouterLink to="profile"> 在嵌套里行为随当前 URL 变化,容易错------to 永远写完整路径或按 name 跳
  4. 默认子路由写成 path: '/' :空 path 是 '','/' 在 children 里是非法/诡异行为
  5. components 单复数搞混 :命名视图用 components(复数)+ RouterView name;普通嵌套用 component(单数)

八、今日小结

  • children 嵌套:父组件里挖第二个 RouterView,子路由 path 不带 /、to 写全路径
  • 默认子路由:空 path + redirect(或直接配组件)
  • 多级嵌套 = 多层出口同时渲染,控制在三四层内
  • 命名视图:components 复数 + RouterView name,同级多出口(低频,认识即可)

下篇预告

后台布局有了,但谁都能访问 /admin 吗?下一篇 049 路由守卫------全局前置守卫、路由独享守卫、组件内守卫三级关卡,手写登录拦截完整流程。

相关推荐
子兮曰27 分钟前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
百度一下吧3 小时前
H5 中 CDN 的加载时机与接入方式
html5
启观川3 小时前
数据结构与算法 -第 3 章 常用算法-动态规划
数据结构·笔记·python·算法
paopaokaka_luck3 小时前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
sm_926787053 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器
IMPYLH4 小时前
HTML 的 <video> 元素
前端·html
一木 之林4 小时前
Dify学习笔记 01 · 平台入门与实战:部署、五类应用、RAG与MCP(第1-16集)
人工智能·笔记·学习·计算机视觉
weixin_448119944 小时前
Datawhale Easy Data × AI:构建知识与记忆驱动的 Agent笔记8
人工智能·笔记·react.js
溪语流沙4 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
逐光者9334 小时前
STM32——SPI 屏 · Flash · 高速
java·前端·stm32