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默认的日志中间件, ...
随机推荐
- AspNetCore开源中间件-VueRouterHistory
前言 用过VueRouter路由组件的应该都知道,VueRouter有hash和history两种模式.hash模式会在url中插入#,history模式下url则看上去更加简洁美观.如果想要支持hi ...
- 在vue-cli中安装scss,且可以全局引入scss的步骤
简历魔板__个人简历模板在线生成 在写vue的css样式时,觉得需要css预处理器让自己的css更加简洁.适应性更强.可读性更佳,更易于代码的维护,于是在vue-cli脚手架采用scss.写过的人都知 ...
- Git生成ssh keys加密算法ed25519
1:桌面右击后出现Git push hehe点击进入直接输入以下命令 ①:ssh-keygen -t ed25519 -f my_github_ed25519 -C "xxxxx" ...
- 试驾 Citus 11.0 beta
https://www.citusdata.com/blog/2022/03/26/test-drive-citus-11-beta-for-postgres/ Citus 11.0 beta 的最大 ...
- data:image字符转byte[]
var data = "data:image/bmp;base64,Qk3aHwAAAAAAADYAAAAoAAAAZAAAABsAAAABABgAAAAAAKQfAAAAAQAAAAEAA ...
- unity---存档方法PlayerPrefs
存档方法 PlayerPrefs 利用键值对的存储方式 存值的方法: PlayerPrefs.SetString("Name",t);//SetInt,SetFloat 取值的方法 ...
- unity---给物体施加普通力和位置力
普通力 让物体沿着某一方向获得一个力,vector3方向 addForceObj.GetComponent<Rigidbody>().AddForce(1000,0,1000); 位置力 ...
- ApeForms | WinForm窗体UI美化库(Metro扁平风格)演示与安装
ApeForms系列① 快速上手 @ 目录 ApeForms系列① 快速上手 前言 演示视频 快速上手 安装及使用 Demo下载 联系开发者 加入我们 建议与咨询 前言 ApeForms是一套基于Wi ...
- T1创世纪(原创)
创世纪 这是我的第一道原创题 题解: 这道题的核心算法是:加维度的最短路+贪心 状态:\(dis[i][j][t][a]\)表示在 \(t\) 时,到达 \((i,j)\) ,当前共造\(a\)只&q ...
- Python 生成图片验证码
验证码图片生成 #!/usr/bin/env python # -*- coding: utf-8 -*- # refer to `https://bitbucket.org/akorn/wheezy ...