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

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

时间2025-04-30 22:27:35分类IT科技浏览4346
导读: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
最新cpu天梯图2021年6月(2022最新CPU天梯图) 怎么申请163电子邮箱(如何申请163电子邮箱,申请163电子邮箱的步骤)