本文主要描述的組織css的問題,文章內容整理自《前端架構設計》的讀書筆記。css
h2{
}
#sidebar h2{
background:red;
}
#sidebar .calendar h2{
background:green;
}
複製代碼
上面這樣寫樣式有很大的問題,主要是咱們在樣式書寫時默認的繼承到了以前的樣式,但在特殊化的樣式時,爲了讓本身的樣式生效,又要新寫樣式進行覆蓋。html
因此列舉一下可能的問題是下面的:前端
在以前的章節中,咱們講到了css不一樣的模塊化方案,那麼對於上面描述的問題,其實能夠很簡化的去解決。vue
你根據以上的需求按照模塊的方案和命名,去除各類依賴,最大程度使用class命名方式,減小繼承,更大程度的使用獨立樣式代碼塊,輕鬆解決了以上的問題。webpack
<h2 class="content_title"></h2>
<div class="sidebar">
<h2 class="content_title--reversed"></h2>
<div class="calendar">
<h2 class="calendar_title"></h2>
</div>
</div>
複製代碼
// 組件文件夾
.content_title{}
// 不用恢復重置樣式
.contitle_title--reverse{}
// 特殊組件的title定義
.calendar_title{
}
複製代碼
好比咱們在定義標題的時候,可能有兩個模塊都用到了標題。web
<div class="calendar">
<h2 class="primary-title"></h2>
</div>
<div class="blog">
<h2 class="primary-title"></h2>
</div>
<style> .primary-title{ } </style>
複製代碼
可能的問題,是咱們須要在日曆或者博客的時候須要去修改這個樣式,因而你的樣式可能變成這樣的。element-ui
.primary-title{
}
.blog .primary-title{}
複製代碼
這樣的問題是會致使選擇器過多,因而咱們按照bem進一步優化。bootstrap
.calendar_header{}
.blog_header{}
複製代碼
這樣維護以後,每一個樣式塊都只負責本身的內容,除了致使代碼的重複以外沒有任何壞處。好處是若是項目嚴格執行單一職責方式,當咱們改動任何代碼的時候,不會擔憂對全局形成的影響。那麼重複的代碼怎麼解決,這個其實webpack的部分和gzip的部分已經能把咱們的代碼進行優化了。api
延伸思考:若是壓縮打包的角度能夠去掉重複代碼的部分,那麼更多角度考慮代碼的可持續、可維護就行了。數組
簡單來說,就是你的樣式代碼應該來源於儘量少的組件,最好是維護在一個class中,保證整個樣式代碼是可追溯的,也能夠預想效果的。
<div class="blog">
<div class="blog-header"></div>
</div>
<div class="calendar">
<div class="calendar-header"></div>
</div>
複製代碼
/* calendar css*/
.calendar-header{
}
/* blog css*/
.blog-header{
}
.blog .blog-header{}
複製代碼
以blog進行title的限定,主要是限制讓字號小一點,這種的主要問題是當項目積累下來,會有不少樣式代碼散落在各個組件,這樣致使不可追溯。(補充個常識,以父元素爲何進行修飾子元素,這個稱爲樣式上下文)
那麼建議的方式是將散落在各處的代碼徹底控制在一個組件內。
雖然單一組件的原則讓咱們對組件的樣式代碼封裝的很好,但仍是有一些特殊的需求,那咱們如何設計這方面的代碼呢?經過皮膚或者子模塊來實現,也能夠稱爲組件修飾符。
好比咱們針對日曆的組件,咱們須要追加一個特殊的樣式,能夠這樣實現。
.calendar-header{
}
.calendar--nested .calendar-header{
}
複製代碼
經過這樣的方式,咱們不但能夠實現皮膚的需求,也能夠實現對上下文的解耦,咱們只要關注組件須要什麼樣的特殊樣式,進行組件修飾便可,而不用依賴耦合在父容器裏。
如下以element的2.4.11版本爲例,根據其api文檔以及源碼的角度爲你們分析element-ui是如何解決這些問題的。
api設計規範:能夠看到button的暴露的api主要是基於屬性的
參數 | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
size | 尺寸 | string | medium / small / mini | — |
type | 類型 | string | primary / success / warning / danger / info / text | — |
plain | 是否樸素按鈕 | boolean | — | false |
round | 是否圓角按鈕 | boolean | — | false |
circle | 是否圓形按鈕 | boolean | — | false |
loading | 是否加載中狀態 | boolean | — | false |
disabled | 是否禁用狀態 | boolean | — | false |
icon | 圖標類名 | string | — | — |
autofocus | 是否默認聚焦 | boolean | — | false |
native-type | 原生 type 屬性 | string | button / submit / reset | button |
class的設計,雖然組件的設計是基於屬性的,但實際不一樣的屬性最終都是表現爲class的。那麼基於這樣的角度去設計樣式是element-ui的獨創或者是vue組件的創新麼?其實早在bootstrap裏就是這樣設計的。
class | 說明 |
---|---|
el-button-group | 按鈕組的樣式,做爲外部容器,不對el-button產生任何樣式代碼,但對其內含有的el-button會產生垂直居中的效果,還有向右的間距,.el-button-group .el-button--primary:first-child{} |
el-button el-button--default | 基本樣式,修飾符,生效規則el-button--default也是直接定義其樣式規則,不依賴於el-button |
el-button el-button--medium | el-button--medium 修飾符中直接定義好尺寸的所有代碼 |
el-button el-button--default is-circle | 基本樣式,smacss狀態樣式 ,其中is-circle包含這個原型的所有樣式,其生效的條件是與el-button同時生效,is-disabled同理 |
icon="el-icon-edit" | 帶icon的部分不在button裏作特殊樣式,其樣式屬於基本樣式,可是dom結構是經過組件進行添加的,那麼其圖標的字號來源於哪裏呢?來源於el-button的基本樣式14px,因此這部分進行了解耦,不用單獨設置 |
組件內如何根據屬性進行返回對應的class.
class="el-button"
// 能夠看到其根據傳入的各個type屬性分別將class追加到class數組之中
:class="[type ? 'el-button--' + type : '',buttonSize ? 'el-button--' + buttonSize : '',{'is-disabled': buttonDisabled,'is-loading': loading,'is-plain': plain,'is-round': round,'is-circle': circle}]"
//根據爲loading 顯示出固定的loading圖標
<i class="el-icon-loading" v-if="loading"></i>
// 根據傳入的icon以及沒有loading顯示出對應type的icon
<i :class="icon" v-if="icon && !loading"></i>
複製代碼
常常有場景咱們須要引入element-ui以後須要對其ui進行皮膚化的開發樣式,雖然element-ui有暴露其對應的組件樣式,咱們也能夠進行對應的詳細的源碼的fork並開發,但在大多數中小公司其實不用小題大作。咱們只須要根據本身的狀況,針對同樣的樣式進行全局樣式覆蓋便可。那麼,咱們項目中針對按鈕的皮膚化改變會是這樣的。
// 定義variables.scss的主題變量
// 主題色相關變量
$color-thin:rgba(60,191,196,0.1);
$color:rgba(60,191,196,1);
// customer-element.scss 主要定義已使用餓了麼組件樣式的修改
@import './variables';
// 一個按鈕樣式的全局覆蓋
.el-button--primary{
&:hover,&:focus{
background:$color;
border-color:$color;
}
background:$color;
border-color:$color;
}
複製代碼
咱們一樣也是分析bootstrap裏的樣式使用,基本也是使用class拼盤理論的。
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-default">Left</button>
<button type="button" class="btn btn-default">Middle</button>
<button type="button" class="btn btn-default">Right</button>
</div>
複製代碼
button.less樣式文件節選,能夠看到其基本樣式、嵌套內僞類的樣式,button-size的方法類,修飾符的(子模塊的)維護方式,這都是值得咱們借鑑的科學規範思想。
// Base styles
// --------------------------------------------------
.btn {
display: inline-block;
......
.button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);
.user-select(none);
&,
&:active,
&.active {
&:focus,
&.focus {
.tab-focus();
}
}
&:hover,
&:focus,
&.focus {
color: @btn-default-color;
text-decoration: none;
}
a& {
&.disabled,
fieldset[disabled] & {
pointer-events: none; // Future-proof disabling of clicks on `<a>` elements
}
}
}
// Alternate buttons
// --------------------------------------------------
.btn-default {
.button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);
}
.btn-primary {
.button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);
}
複製代碼
到此爲止總結的技巧點以下:固然確定還有更多的技巧等待你補充
經過本文咱們瞭解並總結了css代碼的繼承與特殊化的問題,並經過上面的技巧解決了這樣的痛點,並用來顯著提高本身的代碼水平。