您好,登錄后才能下訂單哦!
這篇文章主要介紹Element-ui Layout布局如何實現,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
Element-UI的Layout布局是通過基礎的24分欄,迅速簡便地創建布局。根據不同的組合,很快的就能夠生成一個很美觀的響應式布局。具體的用法如下:
<el-row> <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col> </el-row>
由上述的示例代碼可以看出Row組件主要是創建每行分欄的布局方式,比如之間的一些間隔、對齊方式等。而Col則創建每個分欄,分欄的長度、偏移量等。我們可以進行自由組合每個分欄,從而達到一種響應式效果。
我們都知道vue除了可以使用template模板編寫組件外,有時候我們還可以直接使用render函數去編寫一個組件。因為template模板最終也是編譯成了render函數。
為什么會有render函數的寫法?比如現在有個需求:根據動態的level生成從h2-h7字體大小的標題的時候,我們如果使用template去實現的話我們頁面中可能會出現很多類似這樣的偽代碼:
<template> <h2 v-if="level === 1"> <slot></slot> </h2> <h3 v-else-if="level === 2"> <slot></slot> </h3> <h4 v-else-if="level === 3"> <slot></slot> </h4> <h5 v-else-if="level === 4"> <slot></slot> </h5> <h6 v-else-if="level === 5"> <slot></slot> </h6> <h7 v-else-if="level === 6"> <slot></slot> </h7> </template>
但是如果是使用render函數則是比較簡單:
Vue.component('anchored-heading', { render: function (createElement) { return createElement( 'h' + this.level, // 標簽名稱 this.$slots.default // 子節點數組 ) }, props: { level: { type: Number, required: true } } })
這里還有一個代碼優化點是。this.$slots.default存儲的就是插槽內容,不需要寫那么多遍。
Row組件的源碼比較簡單,因為我們可以通過tag這個prop對其指定一個渲染標簽,所以組件是直接使用render渲染函數進行編寫。 render函數部分如下:
render(h) { return h(this.tag, { class: [ 'el-row', this.justify !== 'start' ? `is-justify-${this.justify}` : '', this.align !== 'top' ? `is-align-${this.align}` : '', { 'el-row--flex': this.type === 'flex' } ], style: this.style }, this.$slots.default); }
如上的源碼可以得出Row主要是控制class名來進行控制內容布局的。這里有gutter屬性能夠控制行內列的間隔數。如果說我們設置為gutter=20,那么每個列項都進行左右間距10px,那么就會出現個問題:第一個列項跟最后一個列項會出現左右的間距。那該如何讓第一個跟最后一個左右間隔去掉這個10px呢?Row的處理方案是這個行左右各偏-10px,所以用了一個計算屬性來設置樣式:
computed: { style() { const ret = {}; if (this.gutter) { ret.marginLeft = `-${this.gutter / 2}px`; ret.marginRight = ret.marginLeft; } return ret; } },
Col主要是為了設置每一列的長度以及偏移量。主要的屬性是span、offset;同樣這個組件也是采用render函數去編寫,首先我們看如何通過span、offset去控制列的,源碼如下:
render(h) { let classList = []; let style = {}; ... ['span', 'offset', 'pull', 'push'].forEach(prop => { if (this[prop] || this[prop] === 0) { classList.push( prop !== 'span' ? `el-col-${prop}-${this[prop]}` : `el-col-${this[prop]}` ); } }); ... return h(this.tag, { class: ['el-col', classList], style }, this.$slots.default); }
從這可以看出,col的列寬是通過不同class名去做控制的。我們找到對應的.scss文件,發現他使用了sass@for循環語句去計算不同格子的寬度:
@for $i from 0 through 24 { .el-col-#{$i} { width: (1 / 24 * $i * 100) * 1%; } .el-col-offset-#{$i} { margin-left: (1 / 24 * $i * 100) * 1%; } .el-col-pull-#{$i} { position: relative; right: (1 / 24 * $i * 100) * 1%; } .el-col-push-#{$i} { position: relative; left: (1 / 24 * $i * 100) * 1%; } }
同理offset也是使用相同的邏輯。這樣我們就可以根據不同的span、跟offset混合組合不同風布局了,是不是感覺背后的邏輯是如此的簡單呢。我們再思考一個問題就是如果我們要控制一組相同的列寬間隔,需要一個個的去做設置么?答案是不用的,我們可以借助上述的Row組件中的gutter屬性去做統一設置。那怎么實現的呢?源碼如下:
computed: { gutter() { let parent = this.$parent; while (parent && parent.$options.componentName !== 'ElRow') { parent = parent.$parent; } return parent ? parent.gutter : 0; } }
我們通過往上遍歷父組件,如果父組件的組件名為ElRow,則取到gutter值,然后讓組件左右內邊距設置對應的值就好了:
if (this.gutter) { style.paddingLeft = this.gutter / 2 + 'px'; style.paddingRight = style.paddingLeft; }
這樣我們就解決了統一列寬設置的問題;
這里我們用到了css3中的媒體查詢來進行響應式布局,相應尺寸分別是xs、sm、md、lg 和 xl。使用代碼如下:
<el-row :gutter="10"> <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple"></div></el-col> <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"><div class="grid-content bg-purple-light"></div></el-col> <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"><div class="grid-content bg-purple"></div></el-col> <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple-light"></div></el-col> </el-row>
說明:xs:<768px 響應式柵格數或者柵格屬性對象,sm:≥768px 響應式柵格數或者柵格屬性對象,md:≥992px 響應式柵格數或者柵格屬性對象,lg:≥1200px 響應式柵格數或者柵格屬性對象,xl:≥1920px 響應式柵格數或者柵格屬性對象.
背后的邏輯就是不同屏幕尺寸所展示的格子數是不一樣的,而且是根據屏幕寬度進行響應式。首先,我們看是如何進行不同的class綁定的:
['xs', 'sm', 'md', 'lg', 'xl'].forEach(size => { if (typeof this[size] === 'number') { classList.push(`el-col-${size}-${this[size]}`); } else if (typeof this[size] === 'object') { let props = this[size]; Object.keys(props).forEach(prop => { classList.push( prop !== 'span' ? `el-col-${size}-${prop}-${props[prop]}` : `el-col-${size}-${props[prop]}` ); }); } });
這里面xs等屬性也是可以使用對象。所以會有個處理對象的邏輯;以上的js處理的邏輯比較簡單,我們再看一下css是怎么處理這個媒體查詢的邏輯的。
在分析css的時候,我們先了解一個概念,那就是sass中的內置方法map-get。map-get($map,$key)函數的作用就是可以通過$key取到對應的value值,可以理解為就是一個映射關系。如果不存在則不會編譯對應的css。舉個????:
$social-colors: ( dribble: #ea4c89, facebook: #3b5998, github: #171515, google: #db4437, twitter: #55acee ); .btn-dribble{ color: map-get($social-colors,facebook); } // 編譯后 .btn-dribble { color: #3b5998; }
第二個是sass內置方法inspect(value),這個方法就是一個返回一個字符串的表示形式,value是一個sass表達式。舉個????:
$--sm: 768px !default; $--md: 992px !default; $--lg: 1200px !default; $--xl: 1920px !default; $--breakpoints: ( 'xs' : (max-width: $--sm - 1), 'sm' : (min-width: $--sm), 'md' : (min-width: $--md), 'lg' : (min-width: $--lg), 'xl' : (min-width: $--xl) ); @mixin res($breakpoint){ $query:map-get($--breakpoints,$breakpoint) @if not $query { @error 'No value found for `#{$breakpoint}`. Please make sure it is defined in `$breakpoints` map.'; } @media #{inspect($query)} { @content; } } .element { color: #000; @include res(sm) { color: #333; } } // 編譯后的css .element { color: #000; } @media (min-width: 768px) { .element { color: #333; } }
好了,我相信聰明的你已經很好的掌握了這兩個方法,那我們去看一下element是怎么去實現的吧。
其實上述的第二個例子已經道出一二,我們看一下源碼:
$--sm: 768px !default; $--md: 992px !default; $--lg: 1200px !default; $--xl: 1920px !default; $--breakpoints: ( 'xs' : (max-width: $--sm - 1), 'sm' : (min-width: $--sm), 'md' : (min-width: $--md), 'lg' : (min-width: $--lg), 'xl' : (min-width: $--xl) ); /* Break-points -------------------------- */ @mixin res($key, $map: $--breakpoints) { // 循環斷點Map,如果存在則返回 @if map-has-key($map, $key) { @media only screen and #{inspect(map-get($map, $key))} { @content; } } @else { @warn "Undefeined points: `#{$map}`"; } } @include res(xs) { @for $i from 0 through 24 { .el-col-xs-#{$i} { width: (1 / 24 * $i * 100) * 1%; } .el-col-xs-offset-#{$i} { margin-left: (1 / 24 * $i * 100) * 1%; } } } @include res(sm) { ... } @include res(md) { ... } @include res(lg) { ... } @include res(xl) { ... }
這樣我們就會在不同的屏幕尺寸下進行不同的長度以及間隔的展示了,這樣去寫我們的媒體查詢是不是很棒呢?
以上是“Element-ui Layout布局如何實現”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。