一、组件介绍
[官网链接](组件 | Element (gitee.io))
el-container组件是用于布局的容器组件,用于搭建页面的基本结构;
其通常与el-header、el-aside、el-main、el-footer搭配使用。
二、源码分析
2.1 container组件代码
container.vue
<template>
// 外层使用原生section标签
<section class="el-container" :class="{'is-vertical': isVertical}">
// 提供默认插槽
<slot></slot>
</section>
</template>
<script lang="ts">
import { defineComponent, computed, VNode, Component } from 'vue'
export default defineComponent({
name: 'ElContainer',
props: {
direction: {
type: String,
default: '',
},
},
setup(props, { slots }) {
// 判断是否采用垂直布局,若采用垂直布局,则将flex-direction设置为column
const isVertical = computed(() => {
// 显式传入布局方向
if (props.direction === 'vertical') {
return true
} else if (props.direction === 'horizontal') {
return false
}
if (slots && slots.default) {
const vNodes: VNode[] = slots.default()
return vNodes.some(vNode => {
const tag = (vNode.type as Component).name
// 当子元素中包含 `<el-header>` 或 `<el-footer>` 时,全部子元素会垂直上下排列,否则会水平左右排列。
return tag === 'ElHeader' || tag === 'ElFooter'
})
} else {
return false
}
})
return {
isVertical,
}
},
})
</script>
@import 'mixins/mixins';
// BEM命名
@include b(container) {
// flex布局
display: flex;
flex-direction: row;
flex: 1;
flex-basis: auto;
box-sizing: border-box;
min-width: 0;
// 垂直
@include when(vertical) {
flex-direction: column;
}
}
2.2 header组件代码
header.vue
<template>
// 原生header标签
<header class="el-header"
// 设置css局部变量,覆盖全局变量,动态设置header高度
:style="{ '--el-header-height': height }">
// 默认插槽
<slot></slot>
</header>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'ElHeader',
props: {
height: {
type: String,
default: null,
},
},
})
</script>
header.scss
@import 'mixins/mixins';
@import 'common/var';
:root {
--el-header-padding: 0 20px;
// 全局css变量,指定header的默认高度
--el-header-height: 60px;
}
@include b(header) {
padding: var(--el-header-padding);
box-sizing: border-box;
flex-shrink: 0;
// 通过css变量调整高度
height: var(--el-header-height);
}
注: footer/aside的代码实现与header完全一致,不再单独细述
2.3 main组件代码
main.vue
<template>
// 原生main标签
<main class="el-main">
// 默认插槽
<slot></slot>
</main>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'ElMain',
})
</script>
main.scss
@import 'mixins/mixins';
@import 'common/var';
:root {
--el-main-padding: 20px;
}
@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: var(--el-main-padding);
}
2.4 总结:
- container/header/footer/aside/main 内部都使用了对应的html5原生标签,具有语义化;
- container采用flex布局;
- 通过style属性动态设置css局部变量值,覆盖css全局变量,起到动态调整样式的效果。