首页IT科技elementui自定义组件开发(Element 2 组件源码剖析之布局容器)

elementui自定义组件开发(Element 2 组件源码剖析之布局容器)

时间2025-06-20 15:15:39分类IT科技浏览5125
导读:0x00 简介 前文分析过组件的 布局栅格化(Grid Layout ,通过基础的 24 分栏,迅速简便地创建布局。...

0x00 简介

前文分析过组件的 布局栅格化(Grid Layout)             ,通过基础的 24 分栏                   ,迅速简便地创建布局            。

本文将介绍用于布局的容器组件      ,使用 Flexbox 功能将其所控制区域设定为特定的布局      ,方便快速搭建页面的基本结构                   。本文将深入分析组件源码                   ,剖析其实现原理            ,耐心读完      ,相信会对您有所帮助      。 组件文档

更多组件剖析详见 ? ? Element 2 源码剖析组件总览       。

0x01 布局容器

布局容器提供5个组件                   ,支持多层嵌套            ,方便快速搭建页面的基本结构:

<el-container>:布局容器,其下可嵌套<el-header><el-footer><el-aside><el-main>或<el-container>本身                   ,可以放在任何父容器中                   。当子元素中包含<el-header>或<el-footer>时                   ,全部子元素会垂直上下排列,否则会水平左右排列            。 <el-header>:顶部容器            ,其下可嵌套任何元素                   ,只能放在<el-container>中      。 <el-aside>:侧边栏容器      ,其下可嵌套任何元素            ,只能放在<el-container>中                   。 <el-main>:主要区域容器                   ,其下可嵌套任何元素      ,只能放在<el-container>中            。 <el-footer>:底部容器      ,其下可嵌套任何元素                   ,只能放在<el-container>中。

以上组件采用了 flex 布局            ,使用前请确定目标浏览器是否兼容                   。此外      ,<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>

0x02 代码实现

container 布局容器

组件 container 封装了 <section>元素,包含没有后备内容(默认值)的匿名插槽。组件定义了direction的 prop 属性                   ,用于子元素的排列方向            。

// packages\container\src\main.vue <template> <section class="el-container" :class="{ is-vertical: isVertical }"> <slot></slot> </section> </template> <script> export default { name: ElContainer, componentName: ElContainer, props: { direction: String }, computed: { isVertical() { // ... } } }; </script>

若没有定义了direction属性值                   ,组件通过tag判断子元素中包含<el-header>或<el-footer>时,全部子元素会垂直上下排列            ,否则会水平左右排列                   。 componentOptions类型定义

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; } }

header 顶部容器

组件 header 封装了 <header>元素                   ,包含一个slot      。组件定义了height的 prop 属性      ,设置顶部容器高度            ,默认值60px            。

// packages\header\src\main.vue <template> <header class="el-header" :style="{ height }"> <slot></slot> </header> </template> <script> export default { name: ElHeader, componentName: ElHeader, props: { height: { type: String, default: 60px } } }; </script>

aside 侧边栏容器

组件 aside 封装了 <aside>元素                   ,包含一个slot                   。组件定义了width的 prop 属性      ,设置侧边栏宽度      ,默认值300px      。

// packages\aside\src\main.vue <template> <aside class="el-aside" :style="{ width }"> <slot></slot> </aside> </template> <script> export default { name: ElAside, componentName: ElAside, props: { width: { type: String, default: 300px } } }; </script>

main 主要区域(内容)容器

组件 main 封装了 <main>元素                   ,包含一个slot      。

// packages\main\src\main.vue <template> <main class="el-main"> <slot></slot> </main> </template> <script> export default { name: ElMain, componentName: ElMain }; </script>

footer 底部容器

组件 footer 封装了 <footer>元素            ,包含一个slot                   。组件定义了height的 prop 属性      ,设置顶部容器高度                   ,默认值60px            。

// packages\footer\src\main.vue <template> <footer class="el-footer" :style="{ height }"> <slot></slot> </footer> </template> <script> export default { name: ElFooter, componentName: ElFooter, props: { height: { type: String, default: 60px } } }; </script>

0x03 组件样式

组件样式源码使用scss的混合指令b            、when嵌套生成组件样式      。

// packages\theme-chalk\src\common\var.scss $--header-padding: 0 20px !default; $--footer-padding: 0 20px !default; $--main-padding: 20px !default; // packages\theme-chalk\src\container.scss @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; } } // packages\theme-chalk\src\header.scss @include b(header) { padding: $--header-padding; box-sizing: border-box; flex-shrink: 0; } // packages\theme-chalk\src\footer.scss @include b(footer) { padding: $--footer-padding; box-sizing: border-box; flex-shrink: 0; } // packages\theme-chalk\src\main.scss @include b(main) { // IE11 supports the <main> element partially https://caniuse.com/#search=main display: block; flex: 1; flex-basis: auto; overflow: auto; box-sizing: border-box; padding: $--main-padding; } // packages\theme-chalk\src\aside.scss @include b(aside) { overflow: auto; box-sizing: border-box; flex-shrink: 0; }

使用gulpfile.js编译scss文件转换为CSS,经过浏览器兼容                   、格式压缩            ,最后生成样式内容如下                   。

/* packages\theme-chalk\lib\container.css */ .el-container { display: flex; flex-direction: row; flex: 1; flex-basis: auto; box-sizing: border-box; min-width: 0; } .el-container.is-vertical { flex-direction: column; } /* packages\theme-chalk\lib\main.css */ .el-main { display: block; flex: 1; flex-basis: auto; overflow: auto; box-sizing: border-box; padding: 20px; } /* packages\theme-chalk\lib\aside.css */ .el-aside { overflow: auto; box-sizing: border-box; flex-shrink: 0; } /* packages\theme-chalk\lib\header.css */ .el-header { padding: 0 20px; box-sizing: border-box; flex-shrink: 0; } /* packages\theme-chalk\lib\footer.css */ .el-footer { padding: 0 20px; box-sizing: border-box; flex-shrink: 0; }

容器布局实现使用 CSS Flexbox,flex-basis      、flex-shrink      、flex 等属性的语法内容请阅读 Flex 布局教程:语法篇 阮一峰            。

前文曾提到<el-container>的子元素只能是后四者,后四者的父元素也只能是<el-container>。因为 只有container 组件指定为 Flex 布局                   ,其余组件若是想要Flex 布局生效                   ,只能将组件作为 container 的子组件,当然 container 可以自包含                   。

0x04 关注专栏

此文章已收录到专栏中 ?            ,可以直接关注                   。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
规划企业网站要经过哪些步骤?(规划网站建设的主要工作流程)