1.vue router里的Layout到底是个啥?
做Vue项目时,你有没有遇到过“每个页面都要重复写导航栏、侧边栏”的烦恼?或者登录页和后台页需要完全不同的页面结构,不知道咋拆分?这时候就得聊聊vue - router里的Layout怎么玩了,Layout看似是个简单的布局概念,实际能帮我们解决页面结构复用、项目维护性的大问题,下面从基础到实战,一步步把Layout的门道理清楚。
你可以把Layout理解成“页面的骨架”,比如做后台管理系统时,左边是侧边栏菜单、顶部是面包屑和用户信息、中间一大块是页面内容 —— 这整套结构就是Layout,它本质是个Vue组件,里面会放`举个例子:新建一个MainLayout.vue
,里面写好侧边栏、顶栏的HTML和逻辑,然后在模板里留个<router - view/>
,之后所有后台页面(比如订单列表、用户管理)都作为这个Layout的“子内容”,路由切换时,只有<router - view>
变,侧边栏、顶栏始终在那儿,这样就不用每个页面都重复写导航代码了。
为啥非要单独搞个Layout?直接写页面不行吗?
要是项目只有三五个页面,直接写确实没毛病,但页面一多,问题就来了:
- 重复代码恶心人:导航栏、页脚、权限校验逻辑,每个页面都复制粘贴?改个导航菜单得改十几个文件,这谁顶得住!
- 结构维护难:登录页不需要导航,后台页需要;营销页要大横幅,内页要侧边栏…不同页面结构差异大时,全写在页面里会让代码乱成一锅粥。
- 团队协作效率低:UI同学改个公共样式,得每个页面找一遍;前端新人接手,得在一堆页面里找公共部分在哪,头都大了。
而Layout把“公共骨架”和“页面内容”拆分开,骨架只写一次,内容只关心业务 —— 复用性、维护性直接提升好几个档次。
手把手配置:vue - router里的Layout咋用?
步骤1:创建Layout组件
先建个布局组件,比如src/layouts/MainLayout.vue
:
<template> <div class="main - layout"> <!-- 侧边栏 --> <aside class="sidebar"> <SidebarMenu /> <!-- 假设这是封装好的菜单组件 --> </aside> <!-- 主体区域 --> <div class="main - content"> <TopBar /> <!-- 顶栏组件 --> <router - view /> <!-- 关键!这里渲染子页面 --> </div> </div> </template>
步骤2:在路由里配置父路由 + 子路由
打开src/router/index.js
,把Layout作为父路由,子路由对应具体页面:
import { createRouter, createWebHashHistory } from 'vue - router' import MainLayout from '@/layouts/MainLayout.vue' import Dashboard from '@/views/Dashboard.vue' import UserList from '@/views/UserList.vue' const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/admin', component: MainLayout, // 父路由用Layout children: [ // 子路由们 { path: 'dashboard', component: Dashboard }, { path: 'users', component: UserList }, ] } ] })
这样,当访问/admin/dashboard
时,MainLayout会被渲染,Dashboard组件插入到MainLayout的<router - view>
里,侧边栏、顶栏自然就跟着出现了。
复杂场景:Layout里的嵌套路由咋处理?
如果Layout里的侧边栏菜单还要分二级导航(订单管理”下有“订单列表”“退款列表”),这时候需要嵌套路由 + Layout内的<router - view>
。
给MainLayout里的侧边栏再加个<router - view>
,用来渲染二级页面:
<!-- MainLayout.vue 里新增二级路由出口 --> <template> <div class="main - layout"> <aside class="sidebar"> <SidebarMenu /> </aside> <div class="main - content"> <TopBar /> <router - view name="secondary" /> <!-- 命名视图,渲染二级内容 --> </div> </div> </template>
然后在路由里配置嵌套:
routes: [ { path: '/admin', component: MainLayout, children: [ { path: 'orders', component: OrdersLayout, // 假设这是二级Layout(包含订单相关的公共结构) children: [ { path: 'list', component: OrderList, meta: { layoutOutlet: 'secondary' } }, { path: 'refund', component: RefundList, meta: { layoutOutlet: 'secondary' } }, ] } ] } ]
这里用了命名视图和meta标记,让二级页面精准渲染到Layout里的指定<router - view>
,实现多层嵌套布局。
不同页面要不同Layout,咋搞?
比如登录页、404页不需要后台Layout,营销首页要大横幅Layout,后台页要侧边栏Layout,这时候得搞多Layout方案:
方法1:路由meta指定Layout
先建多个Layout:PublicLayout.vue
(放营销页布局)、AuthLayout.vue
(登录注册页布局)、MainLayout.vue
(后台布局)。
然后在路由里用meta标记需要的Layout:
routes: [ { path: '/', component: PublicLayout, children: [{ path: '', component: HomePage }] }, { path: '/login', component: AuthLayout, children: [{ path: '', component: LoginPage }] }, { path: '/admin', component: MainLayout, meta: { requiresAuth: true }, children: [...] } ]
方法2:全局路由守卫动态选Layout
如果页面是否需要Layout要根据权限、角色判断(比如普通用户和管理员用不同Layout),可以在router.beforeEach
里处理:
router.beforeEach((to, from, next) => { const layoutComponent = determineLayout(to) // 自定义方法,根据to的信息选Layout to.meta.layout = layoutComponent next() })
然后在App.vue
里动态渲染Layout:
<template> <component :is="currentLayout"> <router - view /> </component> </template> <script setup> import { computed } from 'vue' import { useRoute } from 'vue - router' import MainLayout from '@/layouts/MainLayout.vue' import PublicLayout from '@/layouts/PublicLayout.vue' const route = useRoute() const currentLayout = computed(() => { return route.meta.layout || MainLayout // 默认用MainLayout }) </script>
这样,不同路由就能自动匹配不同Layout,灵活应对多布局场景。
实战优化:Layout性能和维护咋兼顾?
优化1:异步加载Layout
把Layout写成异步组件,减少首屏加载体积:
const MainLayout = () => import('@/layouts/MainLayout.vue')
优化2:用keep - alive缓存Layout内组件
如果Layout里的侧边栏、顶栏有频繁切换的tab页,用<keep - alive>
缓存<router - view>
,避免重复渲染:
<template> <div class="main - layout"> <aside class="sidebar"><SidebarMenu /></aside> <div class="main - content"> <TopBar /> <keep - alive> <router - view /> </keep - alive> </div> </div> </template>
优化3:拆分Layout为原子组件
把侧边栏、顶栏、面包屑这些公共部分拆成单独的小组件(比如SidebarMenu.vue
、TopBar.vue
),让Layout只负责“组装”,代码更易维护:
<template> <div class="main - layout"> <SidebarMenu :menus="menus" /> <div class="main - content"> <TopBar :user="user" /> <Breadcrumb :routes="routes" /> <router - view /> </div> </div> </template>
看完这些,你应该能明白:Layout是vue - router里“偷懒又高效”的布局方案 —— 用组件化思维把公共结构抽出来,让页面只关心业务,不管是简单的后台系统,还是复杂的多布局官网,掌握Layout的配置、嵌套、动态切换,项目结构会清爽很多,下次写项目时,别再把导航栏复制十遍了,试试Layout,效率直接拉满~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。