Element UI 布局容器 Container 完全指南:el-container 系列组件源码解析与实战布局方案
【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element
本篇指南围绕 Vue.js 2.0 组件库 Element UI(当前仓库eleme/element)中的布局容器组件展开,系统讲解<el-container>、<el-header>、<el-aside>、<el-main>、<el-footer>五个组件的职责划分、flex 布局原理、direction自动判定逻辑,以及七种经典页面骨架与一个完整后台管理实例的写法。读完本文,你将掌握用这几行组件快速搭建页头、侧边栏、主内容区、底栏任意组合的页面结构,并能结合源码理解其内部实现与属性默认值,在开发中做到即拿即用、心中有数。
组件总览:五个容器各司其职
Container 系列是 Element UI 中专门用于搭建页面基本结构的容器组件。官方文档(见 examples/docs/en-US/container.md)将其划分为五类:
| 组件 | 语义 | 职责 |
|---|---|---|
<el-container> | 外层容器 | 包裹其余四个组件,决定子元素排列方向 |
<el-header> | 顶栏容器 | 承载页面头部、工具栏、用户信息等 |
<el-aside> | 侧边栏容器 | 承载侧边导航、次要信息栏 |
<el-main> | 主要区域容器 | 承载页面主体内容 |
<el-footer> | 底栏容器 | 承载版权信息、页脚工具等 |
在仓库中,五个组件分别位于独立包内,实现非常轻量,均只包含一个根元素与一个插槽(<slot>):
- packages/container/src/main.vue:渲染
<section class="el-container"> - packages/header/src/main.vue:渲染
<header class="el-header"> - packages/aside/src/main.vue:渲染
<aside class="el-aside"> - packages/main/src/main.vue:渲染
<main class="el-main"> - packages/footer/src/main.vue:渲染
<footer class="el-footer">
每个包入口(如 packages/container/index.js)都会注册install方法,通过Vue.component(Component.name, Component)完成全局注册,因此五个组件在引入 Element UI 后即可直接使用。
布局原理:flex 与 is-vertical 的自动判定
Container 系列采用 CSS flex 布局实现。从 packages/theme-chalk/src/container.scss 可以看到.el-container的完整样式:
@include b(container) { display: flex; flex-direction: row; flex: 1; flex-basis: auto; box-sizing: border-box; min-width: 0; @include when(vertical) { flex-direction: column; } }核心逻辑是:.el-container默认为水平方向(flex-direction: row),一旦加上is-vertical修饰类则切换为垂直方向(flex-direction: column)。
is-vertical由 packages/container/src/main.vue 中的计算属性isVertical决定,其判定优先级如下:
- 显式传入
direction="vertical"→ 强制垂直; - 显式传入
direction="horizontal"→ 强制水平; - 未传
direction时,遍历默认插槽中的 VNode,只要存在el-header或el-footer子组件,就自动判定为垂直排列,否则为水平排列。
对应源码片段:
computed: { isVertical() { if (this.direction === 'vertical') { return true; } else if (this.direction === 'horizontal') { return false; } return this.$slots && this.$slots.default ? this.$slots.default.some(vnode => { const tag = vnode.componentOptions && vnode.componentOptions.tag; return tag === 'el-header' || tag === 'el-footer'; }) : false; } }这正是官方文档所述规则「子元素中有el-header或el-footer时为垂直,否则为水平」的源码依据。理解这一点后,你就能预判任意嵌套组合的排列方向,而不必记忆模板。
需要特别留意官方文档中的使用限制:
<el-container>的子元素只能是<el-header>、<el-aside>、<el-main>、<el-footer>这四者;反过来,后四者的父元素也只能是<el-container>。
此外,因为整套方案依赖 flex,使用前请确认目标浏览器支持 flex 布局。
常见页面布局:七种骨架一键套用
下面这七种布局是官方文档给出的最常见页面骨架(原样继承自 examples/docs/en-US/container.md),可以直接复制到项目中按需使用。配套 CSS 为演示样式,用于区分各区域背景与文字居中。
<el-container> <el-header>Header</el-header> <el-main>Main</el-main> </el-container> <el-container> <el-header>Header</el-header> <el-main>Main</el-main> <el-footer>Footer</el-footer> </el-container> <el-container> <el-aside width="200px">Aside</el-aside> <el-main>Main</el-main> </el-container> <el-container> <el-header>Header</el-header> <el-container> <el-aside width="200px">Aside</el-aside> <el-main>Main</el-main> </el-container> </el-container> <el-container> <el-header>Header</el-header> <el-container> <el-aside width="200px">Aside</el-aside> <el-container> <el-main>Main</el-main> <el-footer>Footer</el-footer> </el-container> </el-container> </el-container> <el-container> <el-aside width="200px">Aside</el-aside> <el-container> <el-header>Header</el-header> <el-main>Main</el-main> </el-container> </el-container> <el-container> <el-aside width="200px">Aside</el-aside> <el-container> <el-header>Header</el-header> <el-main>Main</el-main> <el-footer>Footer</el-footer> </el-container> </el-container> <style> .el-header, .el-footer { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; } .el-aside { background-color: #D3DCE6; color: #333; text-align: center; line-height: 200px; } .el-main { background-color: #E9EEF3; color: #333; text-align: center; line-height: 160px; } body > .el-container { margin-bottom: 40px; } .el-container:nth-child(5) .el-aside, .el-container:nth-child(6) .el-aside { line-height: 260px; } .el-container:nth-child(7) .el-aside { line-height: 320px; } </style>这七种布局覆盖了最常见的组合需求:
- 顶栏 + 内容区:最简洁的单列结构;
- 顶栏 + 内容区 + 底栏:完整的上下三段式;
- 侧边栏 + 内容区:经典左右两栏;
- 顶栏 +(侧边栏 + 内容区):嵌套容器实现「顶部通栏 + 下部左右分栏」;
- 顶栏 +(侧边栏 +(内容区 + 底栏)):三段式中仅主区域下方带底栏;
- 侧边栏 +(顶栏 + 内容区):侧栏通高、右侧上下分栏;
- 侧边栏 +(顶栏 + 内容区 + 底栏):最完整的后台管理骨架。
注意第 4~7 种布局都体现了「容器内嵌套容器」的用法,嵌套时内层<el-container>会自动根据其直接子元素(是否含el-header/el-footer)决定自己的排列方向,无需手动指定。
实战实例:完整的后台管理页布局
官方文档还给出了一个完整的「后台管理系统」示例:左侧为多级侧边导航(el-menu),右上为带下拉菜单的工具区(el-dropdown),中间主区域为数据表格(el-table)。该示例综合运用了 Container 系列与 Element UI 其他组件的组合能力,可直接改造为实际业务页面。
<el-container style="height: 500px; border: 1px solid #eee"> <el-aside width="200px" style="background-color: rgb(238, 241, 246)"> <el-menu :default-openeds="['1', '3']"> <el-submenu index="1"> <template slot="title"><i class="el-icon-message"></i>Navigator One</template> <el-menu-item-group> <template slot="title">Group 1</template> <el-menu-item index="1-1">Option 1</el-menu-item> <el-menu-item index="1-2">Option 2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="Group 2"> <el-menu-item index="1-3">Option 3</el-menu-item> </el-menu-item-group> <el-submenu index="1-4"> <template slot="title">Option4</template> <el-menu-item index="1-4-1">Option 4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-menu"></i>Navigator Two</template> <el-menu-item-group> <template slot="title">Group 1</template> <el-menu-item index="2-1">Option 1</el-menu-item> <el-menu-item index="2-2">Option 2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="Group 2"> <el-menu-item index="2-3">Option 3</el-menu-item> </el-menu-item-group> <el-submenu index="2-4"> <template slot="title">Option 4</template> <el-menu-item index="2-4-1">Option 4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="3"> <template slot="title"><i class="el-icon-setting"></i>Navigator Three</template> <el-menu-item-group> <template slot="title">Group 1</template> <el-menu-item index="3-1">Option 1</el-menu-item> <el-menu-item index="3-2">Option 2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="Group 2"> <el-menu-item index="3-3">Option 3</el-menu-item> </el-menu-item-group> <el-submenu index="3-4"> <template slot="title">Option 4</template> <el-menu-item index="3-4-1">Option 4-1</el-menu-item> </el-submenu> </el-submenu> </el-menu> </el-aside> <el-container> <el-header style="text-align: right; font-size: 12px"> <el-dropdown> <i class="el-icon-setting" style="margin-right: 15px"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>View</el-dropdown-item> <el-dropdown-item>Add</el-dropdown-item> <el-dropdown-item>Delete</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <span>Tom</span> </el-header> <el-main> <el-table :data="tableData"> <el-table-column prop="date" label="Date" width="140"> </el-table-column> <el-table-column prop="name" label="Name" width="120"> </el-table-column> <el-table-column prop="address" label="Address"> </el-table-column> </el-table> </el-main> </el-container> </el-container> <style> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style> <script> export default { data() { const item = { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' }; return { tableData: Array(20).fill(item) } } }; </script>该实例的结构要点:外层<el-container>只含<el-aside>与内层<el-container>(无el-header/el-footer直接子元素),因此外层水平排列;内层容器直接子元素含<el-header>,因此自动垂直排列。用户信息展示、下拉菜单、数据表格分别放在header与main区域中,aside通过width="200px"控制侧栏宽度。
属性 API 详解
四个组件各自暴露的属性非常精简,官方文档(examples/docs/en-US/container.md)给出的参数表如下:
Container Attributes
| 属性 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| direction | 子元素的排列方向 | string | horizontal / vertical | 子元素中有el-header或el-footer时为 vertical,否则为 horizontal |
direction对应源码 packages/container/src/main.vue 中的props.direction,其作用是强制覆盖自动判定逻辑:传入vertical强制垂直、horizontal强制水平,不传则由isVertical计算属性按插槽内容推断。这在需要「包含 header/footer 却仍想水平排列」或反之的特殊场景下非常有用。
Header Attributes
| 属性 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| height | 顶栏高度 | string | — | 60px |
源码中height类型为String,默认'60px',通过内联样式:style="{ height }"绑定到<header>元素(见 packages/header/src/main.vue)。传入任何合法 CSS 长度值(如80px、4rem)都会被原样应用。
Aside Attributes
| 属性 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| width | 侧边栏宽度 | string | — | 300px |
源码中width类型为String,默认'300px',通过内联样式:style="{ width }"绑定到<aside>元素(见 packages/aside/src/main.vue)。注意文档示例中普遍使用width="200px",而默认值是300px,不传该属性时侧栏会按 300px 渲染。
Footer Attributes
| 属性 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| height | 底栏高度 | string | — | 60px |
与Header的height完全对称,默认'60px',见 packages/footer/src/main.vue。
至于<el-main>,官方文档未列出任何属性,其源码 packages/main/src/main.vue 也确认它只声明了组件名、没有 props,纯粹作为内容承载区使用。
源码与测试验证
仓库单元测试 test/unit/specs/container.spec.js 对上述行为做了完整覆盖,可作为实现事实的印证:
vertical用例:渲染包含<el-header>的容器后,断言根元素包含is-verticalclass;direction用例:先传direction="horizontal"断言不含is-vertical,再动态改为vertical并在$nextTick后断言 class 更新——验证了direction的响应式覆盖能力;height/width用例:分别给<el-header height="100px">、<el-aside width="200px">、<el-footer height="100px">传参,断言最终el.style.height/el.style.width等于传入值——验证了属性通过内联样式生效;- 各组件
create用例:验证组件可正常创建渲染。
从源码结构还可以推断:is-vertical依赖$slots.default中 VNode 的componentOptions.tag来识别子组件类型,因此判定发生在渲染阶段;这也意味着嵌套容器时,每一层都独立计算自己的方向,外层是否垂直不影响内层判定。
使用注意事项与最佳实践
- 方向判定规则要牢记:
direction显式值 > 插槽内容推断;推断只看直接子元素中是否出现el-header/el-footer。想要不受插槽影响地控制方向,务必显式传direction。 - 嵌套层级按需拆分:复杂页面建议将「顶部通栏」「侧栏通高」「主区上下分栏」拆成独立的内层
<el-container>,代码可读性更好,也避免一个容器内堆叠过多子元素导致方向推断出错。 - 宽度高度用 CSS 长度字符串:
width/height接受任何 CSS 长度值,如200px、20%、10rem;需响应式侧栏时可在aside外层再套一层控制宽度的容器。 - 配合其他布局组件使用:Container 系列负责整体骨架,内部单元格的栅格划分可交给
el-row/el-col(见 packages/row/src/row.js 与 packages/col/src/col.js),两者组合即可覆盖从页面骨架到内容栅格的全链路布局需求。 - 浏览器兼容性:整体基于 flex,旧浏览器(如 IE9 及以下)不适用;现代浏览器均可放心使用。
综上,Element UI 的 Container 系列以极少的 API 和清晰的 flex 实现,提供了搭建任何常见页面骨架所需的全部能力。只要掌握了「外层容器 + 四种子容器」「direction 自动推断 + 显式覆盖」「嵌套容器独立判定」三个核心规律,就可以自由组合出任意形态的页面结构。
【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考