使用container的嵌套_ElementUI 技术揭秘(4)— Container 布局容器组件的设计与实现。...
前言
上一篇文章我們分析了 Layout 布局組件的設計和實現,它的應用場景通常是局部布局。對于整個頁面的布局,element-ui 提供了 Container 布局容器組件,專門用于 PC 管理后臺頁面的整體布局。
需求分析
我們先通過幾幅圖看一下頁面的常見布局。
這兩張圖的布局在后臺系統中很常見,通過簡單的 CSS 就可以實現。不過我們更喜歡用組件化的開發方式,把這些 CSS 的細節封裝到組件里,如下:
<el-container>??<el-header>Headerel-header>
??<el-main>Mainel-main>
??<el-footer>Footerel-footer>
el-container>
<el-container>
??<el-header>Headerel-header>
??<el-container>
????<el-aside?width="200px">Asideel-aside>
????<el-container>
??????<el-main>Mainel-main>
??????<el-footer>Footerel-footer>
????el-container>
??el-container>
el-container>
我們使用了 、、、、 5 種組件,來看一下它們各自的作用:
:外層容器。當子元素中包含 或 時,全部子元素會垂直上下排列,否則會水平左右排列。
:頂欄容器。
:側邊欄容器。
:主要區域容器。
:底欄容器。
這幾個組件需要遵循如下約束:
的子元素只能是后四者,后四者的父元素也只能是 。
了解了 element-ui Container 布局容器組件的需求后,我們來分析它的設計和實現。
設計和實現
針對圖示的布局,我們可以通過 flex 的布局方式輕松實現,element-ui 也是基于 flex 布局實現的,接下來我們來分析各個組件的實現。
ElContainer 組件
先來看模板部分:
<template>??<section?class="el-container">
????<slot>slot>
??section>
template>
組件會渲染成一個 標簽,并通過 slot 做內容分發。
再來看一下 CSS 部分:
@include?b(container)?{??display:?flex;
??flex-direction:?row;
??flex:?1;
??flex-basis:?auto;
??box-sizing:?border-box;
??min-width:?0;
}
重點看一下 CSS 部分,display:flex 創建了一個 flex 容器,flex-direction:row 指定了內部元素是在水平方向排列。這里為什么還有 flex:1 呢,因為 容器是支持嵌套的,并且我們知道 flex:1 相當于 flex-grow:1;flex-shrink:1;flex-basis:0,也就是當 被嵌套的時候,它會占滿剩余空間。flex-basis:auto?表示分配空間之前會先跟父容器預約自身內容大小的空間,然后剩下的才會歸入到剩余空間。
容器默認是水平排列,當然也需要支持垂直排列,我們可以給組件提供一個 direction 的 prop,如果傳入的 direction 是 vertical,添加對應的 CSS。
<template>??<section?class="el-container"?:class="{?'is-vertical':?isVertical?}">
????<slot>slot>
??section>
template>
export?default?{
??name:?'ElContainer',
??componentName:?'ElContainer',
??props:?{
????direction:?String
??},
??computed:?{
????isVertical()?{
??????if?(this.direction?===?'vertical')?{
????????return?true;
??????}?else?if?(this.direction?===?'horizontal')?{
????????return?false;
??????}
????}
??}
};@include?when(vertical)?{
}
如果傳入的 direction 為 vertical,則添加 is-vertical 的 CSS,最終通過修改 flex-direction:column 實現內部元素是在垂直方向排列。
回顧前面的一個需求:當 容器的子元素中包含 或 時,全部子元素會垂直上下排列,否則會水平左右排列。
實現它也很容易,擴展計算屬性 isVertical 的判斷條件即可:
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;?
??}
}
這里用了一個小技巧,this.$slots.default 獲取的是默認插槽中的所有 vnodes 節點,然后對他們遍歷,通過 vnode.componentOptions.tag 來判斷這個 vnode 是不是 或者是 。vnode.componentOptions 并不在官網 API 里,但是對于熟讀 Vue 源碼的人來說并不陌生。
ElHeader 組件
先來看一下模板部分:
<template>??<header?class="el-header">
????<slot>slot>
??header>
template>
組件會渲染成一個 標簽,并通過 slot 做內容分發。
再來看一下 CSS 部分:
@include?b(header)?{??padding:?$--header-padding;
??box-sizing:?border-box;
??flex-shrink:?0;
}
其中 $--header-padding 是一個變量,在 packages/theme-chalk/src/common/var.scss 文件中定義。flex-shrink: 0 表示即使空間不夠,也不會縮小 所占空間。
通常來說頭部都會有一個固定高度,因此 允許你傳入一個 height 的 props 來指定高度,如果不指定的話提供一個默認高度。
<template>??<header?class="el-header"?:style="{?height?}">
????<slot>slot>
??header>
template>
export?default?{
??name:?'ElHeader',
??componentName:?'ElHeader',
??props:?{
????height:?{
??????type:?String,
??????default:?'60px'
????}
??}
};
由于直接通過 :style 設置的樣式,所以這里傳入高度的時候一定要攜帶單位。
ElMain 組件
先來看一下模板部分:
<template>??<main?class="el-main">
????<slot>slot>
??main>
template>
組件會渲染成一個 標簽,并通過 slot 做內容分發。
再來看一下 CSS 部分:
@include?b(main)?{??//?IE11?supports?the??element?partially?https://caniuse.com/#search=main
??display:?block;
??flex:?1;
??flex-basis:?auto;
??overflow:?auto;
??box-sizing:?border-box;
??padding:?$--main-padding;
}
注意, 標簽在 IE11 中是部分支持的。通常 中包裹的內容完全由它的子元素來決定,所以并不會設置高和寬,只是通過 flex:1 來分配 容器的剩余空間。
ElFooter 組件
先來看一下模板部分:
<template>??<footer?class="el-footer">
????<slot>slot>
??footer>
template>
組件會渲染成一個 標簽,并通過 slot 做內容分發。
再來看一下 CSS 部分:
@include?b(footer)?{??padding:?$--footer-padding;
??box-sizing:?border-box;
??flex-shrink:?0;
}
和頭部一樣,通常底部也會有一個固定高度,因此 允許你傳入一個 height 的 props 來指定高度,如果不指定的話提供一個默認高度。
<template>??<footer?class="el-footer"?:style="{?height?}">
????<slot>slot>
??footer>
template>
export?default?{
??name:?'ElFooter',
??componentName:?'ElFooter',
??props:?{
????height:?{
??????type:?String,
??????default:?'60px'
????}
??}
};
ElAside 組件
先來看一下模板部分:
<template>??<aside?class="el-aside">
????<slot>slot>
??aside>
template>
組件會渲染成一個 標簽,并通過 slot 做內容分發。
再來看一下 CSS 部分:
@include?b(aside)?{??overflow:?auto;
??box-sizing:?border-box;
??flex-shrink:?0;
}
組件用來渲染側邊欄,而側邊欄通常會有寬度,因此 ,允許你傳入一個 width 的 props 來指定寬度,如果不指定的話提供一個默認寬度。
<template>??<aside?class="el-aside"?:style="{?width?}">
????<slot>slot>
??aside>
template>
export?default?{
??name:?'ElAside',
??componentName:?'ElAside',
??props:?{
????width:?{
??????type:?String,
??????default:?'300px'
????}
??}
};
總結
element-ui 的 Container 布局容器組件的實現還是很簡單的:創建了一些語義化的標簽,利用插槽做內容分發,通過 flex 實現布局效果。
學習完這篇文章,你可以順便對 flex 布局、HTML5 的語義化標簽做一下復習,加深理解,并了解到 Vue 源碼中的一些小技巧。
把不會的東西學會了,那么你就進步了,如果你覺得這類文章有幫助,也歡迎把它推薦給你身邊的小伙伴。
下一篇預告 :Element-UI ?技術揭秘(5)色彩、字體、邊框與圖標。
在這里留下你的爪印喔~
總結
以上是生活随笔為你收集整理的使用container的嵌套_ElementUI 技术揭秘(4)— Container 布局容器组件的设计与实现。...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 破格晋升!一批高校教师脱颖而出
- 下一篇: 在非洲意外当上酋长的河南小伙,现在咋样了