Element 2 组件源码剖析之布局容器
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 关注专栏
此文章已收录到专栏中 ,可以直接关注。
Element 2 组件源码剖析之布局容器的更多相关文章
- Rest_Framework之认证、权限、频率组件源码剖析
一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...
- 转 Spring源码剖析——核心IOC容器原理
Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...
- STL源码剖析——序列式容器#4 Stack & Queue
Stack stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口,元素的新增.删除.最顶端访问都在该出口进行,没有其他位置和方法可以存取stack的元素. ...
- STL源码剖析——序列式容器#2 List
list就是链表的实现,链表是什么,我就不再解释了.list的好处就是每次插入或删除一个元素,都是常数的时空复杂度.但遍历或访问就需要O(n)的时间. List本身其实不难理解,难点在于某些功能函数的 ...
- STL源码剖析——序列式容器#1 Vector
在学完了Allocator.Iterator和Traits编程之后,我们终于可以进入STL的容器内部一探究竟了.STL的容器分为序列式容器和关联式容器,何为序列式容器呢?就是容器内的元素是可序的,但未 ...
- STL源码剖析——序列式容器#3 Deque
Deque是一种双向开口的连续线性空间.所谓的双向开口,就是能在头尾两端分别做元素的插入和删除,而且是在常数的时间内完成.虽然Vector也可以在首端进行元素的插入和删除(利用insert和erase ...
- STL源码剖析——序列式容器#5 heap
准确来讲,heap并不属于STL容器,但它是其中一个容器priority queue必不可少的一部分.顾名思义,priority queue就是优先级队列,允许用户以任何次序将任何元素加入容器内,但取 ...
- Spring源码剖析依赖注入实现
Spring源码剖析——依赖注入实现原理 2016年08月06日 09:35:00 阅读数:31760 标签: spring源码bean依赖注入 更多 个人分类: Java 版权声明:本文为博主原 ...
- Node 进阶:express 默认日志组件 morgan 从入门使用到源码剖析
本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 章节概览 morgan是express默认的日志中间件, ...
随机推荐
- java高级用法之:JNA中的Structure
目录 简介 native中的struct Structure 特殊类型的Structure 结构体数组作为参数 结构体数组作为返回值 结构体中的结构体 结构体中的数组 结构体中的可变字段 结构体中的只 ...
- Atlas2.2.0编译、安装及使用(集成ElasticSearch,导入Hive数据)
1.编译阶段 组件信息: 组件名称 版本 Atals 2.2.0 HBase 2.2.6 Hive 3.1.2 Hadoop 3.1.1 Kafka 2.11_2.4.1 Zookeeper 3.6. ...
- Volatile的学习
首先先介绍三个性质 可见性 可见性代表主内存中变量更新,线程中可以及时获得最新的值. 下面例子证明了线程中可见性的问题 由于发现多次执行都要到主内存中取变量,所以会将变量缓存到线程的工作内存,这样当其 ...
- join方法原理
join()方法--原理同wait方法 如果不知道保护性暂停是啥的可以参考一下上一篇文章 https://www.cnblogs.com/duizhangz/p/16222854.html join方 ...
- 用更云原生的方式做诊断|大规模 K8s 集群诊断利器深度解析
背景 通常而言,集群的稳定性决定了一个平台的服务质量以及对外口碑,当一个平台管理了相当规模数量的 Kubernetes 集群之后,在稳定性这件事上也许会"稍显被动". 我们可能经常 ...
- 给IDEA道个歉,这不是它的BUG,而是反编译插件的BUG。
你好呀,我是歪歪. 上周我不是发了<我怀疑这是IDEA的BUG,但是我翻遍全网没找到证据!>这篇文章吗. 主要描述了在 IDEA 里面反编译后的 class 文件中有这样的代码片段: 很明 ...
- WC2019
好题啊! 数树 \(\text{opt = 0, 6 pts.}\) 显然答案为 \(y^{n-|E_1∩E_2|}\) . \(\text{opt = 1, 47 pts.}\) \[\sum_{E ...
- Redis集群搭建 三主三从
Redis集群介绍 Redis 是一个开源的 key-value 存储系统,由于出众的性能,大部分互联网企业都用来做服务器端缓存.Redis在3.0版本之前只支持单实例模式 虽然支持主从模式,哨兵模式 ...
- SQL Server各版本序列号/激活码/License/秘钥
SQL Server 2019 Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G Enterprise Core:2C9JR-K3RNG-QD4M4-JQ2HR-846 ...
- SAP SD-Invoice 销售发票
针对销售订单的发票流程: 1. 事务码:VF01(个别生成系统发票) 创建开票凭证(发票)/ VF04 开具系统发票(可把多个item 合并成一张系统发票) 2. 事务码:VF02 修改发票, 释放 ...