關鍵概念
<h2 id="block">模塊</h2>
一個在邏輯和功能上獨立的頁面組件,與 Web 組件中的組件概念是等同的。一個模塊封裝了行為(JavaScript),模板,樣式(CSS),和其他技術實現。模塊是獨立的,允許我們重用,從而更好地促進項目的開發。
模塊的特征
嵌套結構
模塊可以被其他的模塊嵌套在內部。
??比如:一個 head
模塊可以包含一個 logo(logo
),一個搜索框(search
),和一個授權(登錄/注冊)模塊(auth
)。

任意位置
模塊可以在一個頁面上使用,在多個頁面間使用,或者在多個項目間使用。模塊被實現為獨立的實體,從而使得在頁面中改變模塊的位置成為可能,同時確保他們的功能和外觀是正常的。
因此,logo 和 認證表單模塊可以在不更改 CSS 和 JavaScript 代碼的情況下互相交換位置。


重用
一個界面可以包含多個相同模塊的實例。

<h2 id="element">元素</h2>
元素是一個模塊的組成部分,并且不可以在模塊之外使用。
例如,一個菜單項不可以被單獨使用在菜單模塊的上下文之外,一次它是一個元素。

<h2 id="modifier">修飾符</h2>
是否使用修飾符,是可選擇的。
本質上,修飾符和 HTML 屬性是相似的。相同的模塊看起來不同,正式由于使用了修飾符。
例如,菜單模塊(menu
)可能會改變它自己的外觀,這取決于一個修飾符被使用在菜單模塊上。

修飾符可以在程序運行時被改變(例如,模塊的某個 DOM 事件被觸發時),或者被其他模塊所改變。
<h2 id="bem-entity">BEM 實體</h2>
這個概念可以被應用在一個單獨的 BEM 實體上,也可以作為模塊,元素和修飾符的統稱。
<h2 id="mix">混合模式</h2>
可以將多個不同的 BEM 實體整合為一個單獨的 DOM 節點。
混合模式允許我們
- 結合多個 BEM 實體的行為和風格(樣式),以及減少代碼的重復
- 在已經存在的 BEM 實體的基礎上創建新的新的界面組件。
讓我們考慮一個將一個模塊和另一個模塊的元素混合的案例。
讓我們假定通過一個 link
模塊來實現你項目中的鏈接。我們需要將菜單項全部用鏈接實現。這有一些方式來實現我們的目的。
- 為菜單項創建一個可以將其轉換為鏈接的修飾符。為了實現這樣一個修飾符,必然會復制
link
模塊的行為和樣式。這將會造成代碼的重復。 - 將一個通用的
link
模塊和一個 ·menu· 模塊的link
元素結合在一起。這兩個 BEM 實體的混合模式允許我們使用link
模塊的鏈接功能,并且可以在不復制代碼的情況下使用menu
模塊額外的 CSS 規則。
<h2 id="beem-tree">BEM 樹</h2>
一種使用模塊,元素和修飾符的 web 頁面結構的表示。是通過 BEM 實體名稱對 DOM 樹的抽象描述,包括他們的狀態,順序,嵌套和一些輔助性的數據。
在真實的項目中,一個 BEM 樹可以被呈現在任何支持樹結構的格式中。
讓我們來看一個 DOM 樹的例子:
<header class="header">
<img class="logo">
<form class="search-form">
<input type="input">
<button type="button"></button>
</form>
<ul class="lang-switcher">
<li class="lang-switcher__item">
<a class="lang-switcher__link" href="url">en</a>
</li>
<li class="lang-switcher__item">
<a class="lang-switcher__link" href="url">ru</a>
</li>
</ul>
</header>
相應的 BEM 樹看起來是這個樣子的
header
├──logo
└──search-form
├──input
└──button
└──lang-switcher
└──lang-switcher__item
└──lang-switcher__link
└──lang-switcher__item
└──lang-switcher__link
在 XML 和 BEMJSON格式中,相同的 BEM 樹如下:
XML
<block:header>
<block:logo/>
<block:search-form>
<block:input/>
<block:button/>
</block:search-form>
<block:lang-switcher>
<elem:item>
<elem:link/>
</elem:item>
<elem:item>
<elem:link/>
</elem:item>
</block:lang-switcher>
</block:header>
BEMJSON
{
block: 'header',
content : [
{ block : 'logo' },
{
block : 'search-form',
content : [
{ block : 'input' },
{ block : 'button' }
]
},
{
block : 'lang-switcher',
content : [
{
elem : 'item',
content : [
{ elem : 'link' }
]
},
{
elem : 'item',
content : [
{ elem : 'link' }
]
}
]
}
]
}
<h2 id="block-implementation">模塊實現</h2>
決定一個 BEM 實體包含如下一組不同的技術:
- 行為
- 外觀
- 測試
- 模板
- 文檔
- 依賴關系描述
- 輔助性數據(例如,圖片)
<h2 id="block-implementation-tec">實現技術</h2>
??用于實現一個模塊的相關技術。
模塊可以使用一種或多種技術實現,比如:
- 行為 —— JavaScript,CoffeeScript
- 外觀 —— CSS,Stylus,Sass
- 模板 —— BEMHTML,BH,Pug,Handlebars,XSL
- 文檔 —— Markdown,Wiki,XML.
例如,如果一個模塊的外觀使用 CSS 定義,這表明這個模塊使用 CSS 技術被實現。同樣。如果使用 Markdown 書寫一個模塊的文檔,那么該模塊使用 Markdown 技術實現。
<h2 id="block-redefinition">模塊重定義</h2>
??通過在不同的級別上添加新的功能來更改模塊的實現。
<h2 id="redefinition-level">重新定義級別</h2>
重定義級別指一組 BEM 實體和他們的部分實現。
模塊的最終實現可以被分成不同的定義級別上。每一個新的級別繼承或者覆蓋之前的對模塊的實現。最終的結果是由按照連續順序的每個重定義的級別上的模塊的實現技術組裝而成的。

每一個級別上對 BEM 實體的實現技術都可以被重新定義。
例如,這里有一個項目,在該項目的一個單獨的級別上使用了一個第三方庫。該第三方庫實現有現成的模塊。該具體項目的模塊被保存在另一個重定義級別上。
比方說,我們需要修飾第三庫其中的某一個模塊的外觀。不需要在第三方庫的源碼中修改模塊的 CSS 規則,或者將代碼復制到項目級別中。我們只需要在項目級別上為模塊創建一些額外的 CSS 規則。在項目構建過程中,最終實現將會結合庫級別的原有規則和項目級別中新的樣式規則。
本人才疏學淺,如果文中有錯誤,或者歧異,或者不恰當的地方,希望大家提出來,非常愿意接受大家的批評與建議。