@GaoyuanHfut
2017-08-02T14:09:07.000000Z
字数 4346
阅读 595
BEM的意思就是块(block)、元素(element)、修饰符(modifier),是由Yandex团队提出的一种前端命名方法论。这种巧妙的命名方法让你的CSS类对其他开发者来说更加透明而且更有意义。BEM命名约定更加严格,而且包含更多的信息,它们用于一个团队开发一个耗时的大项目。
elementUI采用 BEM 风格来写 CSS,这样的好处是类名基本都是一级,少数才会有嵌套情况,这样很容易的就可以直接覆盖掉原有样式。[bem的用法与好处][5].
BEM中的Block一个块是一个独立的实体,就像应用的一块“积木”。一个块既可以是简单的也可以是复合的(包含其他块)。
块的名称是描述了它的用途(“它是什么?” menu或button),而不是它的状态(“它是什么样子的?” red或big)。
<!-- 正确的做法. `error` block 说明了块的意义 -->
<div class="error"></div>
<!-- 错误的做法. "red-text"只描述了他的表面 -->
<div class="red-text"></div>
块可以互相嵌套:
<!-- `header` 块 -->
<header class="header">
<!-- 嵌套的 `logo` 块 -->
<div class="logo"></div>
<!-- 嵌套的 `search-form` 块 -->
<form class="search-form"></form>
</header>
使用@component block-name{...}就可以生成一个Block。
例如搜索表单就是一个块。
添加下面的代码就可以创建一个search-form的Block:
@component search-form {
padding: 0;
margin: 0;
}
编译出来的代码如下:
.search-form {
padding: 0;
margin: 0;
}
BEM中一个元素是块的一部分,具有某种功能。元素是依赖上下文的:它们只有处于他们应该属于的块的上下文中时才是有意义的。(这是它和block最大的区别,后面会提到)
element的名称是描述了它的用途(“它是什么?” item, text, etc.),而不是它的状态(“它是什么样子的?” red或big)。
例如一个输入域和一个按钮是Search块的中的元素。
可以使用@descendent element-name{...}嵌套在Block中,创建一个Element。
你可像下面的代码一样,创建一个名为text-field的Element:
@component search-form {
padding: 0;
margin: 0;
@descendent text-field {
border: 1px solid #ccc;
}
}
编译之后,你就能看到一个新的Element就创建了,以”__”连接表示:
.search-form {
padding: 0;
margin: 0;
}
.search-form__text-field {
border: 1px solid #ccc;
}
元素可以相互嵌套且可以有任意数量的嵌套层数。
元素总是一个块的一部分,而不是另一个元素的子元素。那意味着不允许定义block__elem1__elem2这样的元素.(element中使用了,但我们为了使代码更清晰,不允许这样写)
<!--
正确的做法. 元素名称的结构遵循下面的结构:
`block-name__element-name`
-->
<form class="search-form">
<div class="search-form__content">
<input class="search-form__input">
<button class="search-form__button">Search</button>
</div>
</form>
<!--
错误的做法,没有遵守以下结构:
`block-name__element-name`
-->
<form class="search-form">
<div class="search-form__content">
<!-- 建议: `search-form__input` 或 `search-form__content-input` -->
<input class="search-form__content__input">
<!-- 建议: `search-form__button` 或 `search-form__content-button` -->
<button class="search-form__content__button">Search</button>
</div>
</form>
block的内部允许element 互相嵌套(建议尽量不要这样写)
<div class="block">
<div class="block__elem1">
<div class="block__elem2">
<div class="block__elem3"></div>
</div>
</div>
</div>
元素始终是块的一部分,不应该单独使用它,但不是所有的块都有元素。
选择block
如果一段代码可以重用,且不依赖于正在执行的其他页面组件。
选择element
如果没有父元素(block)则不能单独使用的代码.
开发中如果遇到元素必须要分成更小的部分–子元素–。在这种情况下,您不应该创建一个element,而是需要创建一个block。
尽管BEM允许给Block和Element创建一个Modifier,但postcss-salad插件只会处理嵌套在Block中的Modifier,而不会创建嵌套在Element的Modifier。可以通过@modifier name{...}语法,将Modifier嵌套在它的父块中。
可以像下面的代码一样,给search-form添加一个advanced的Modifier:
@component search-form {
padding: 0;
margin: 0;
@modifier advanced {
padding: 1rem;
}
@descendent text-field {
border: 1px solid #ccc;
}
}
编译出来的代码如下:
.search-form {
padding: 0;
margin: 0;
}
.search-form--advanced {
padding: 1rem;
}
.search-form__text-field {
border: 1px solid #ccc;
}
通过@when name {...}语法嵌套在一个组件(Component)或一个Descendent中可以创建一个State。
在textField添加一个invalid,给textField的Descendent添加一个名为invalid的State:
@component SearchForm {
padding: 0;
margin: 0;
@modifier advanced {
padding: 1rem;
}
@descendent textField {
border: 1px solid #ccc;
/* This creates a state for the textField descendant */
@when invalid {
border: 1px solid red;
}
}
}
编译出来的代码会包括一个名为invalid的State:
.SearchForm {
padding: 0;
margin: 0;
}
.SearchForm--advanced {
padding: 1rem;
}
.SearchForm__textField {
border: 1px solid #ccc;
}
.SearchForm-textField.is-invalid {
border: 1px solid red;
}
通过@component-namespace name {...}可以给组件(Components)创建命名空间,而且Descendents,Modifiers和States都嵌套在里面。如果你喜欢,整个样式表都可以采用命名空间,而且可以自动添加到类的前面。
使用@component-namespace mine{...}给容器添加一个命名空间:
@component-namespace mine {
@component SearchForm {
padding: 0;
margin: 0;
@modifier advanced {
padding: 1rem;
}
@descendent textField {
border: 1px solid #ccc;
@when invalid {
border: 1px solid red;
}
}
}
}
编译出来的代码,会在你的组件前添加一个mine-前缀。如:
.mine-SearchForm {
padding: 0;
margin: 0;
}
.mine-SearchForm--advanced {
padding: 1rem;
}
.mine-SearchForm-textField {
border: 1px solid #ccc;
}
.mine-SearchForm-textField.is-invalid {
border: 1px solid red;
}
下面是postcss-salad的配置文件:
"shortcuts": {//简化写法
"component": "b",//@b=@component
"modifier": "m",//@m=@ modifier
"descendent": "e"//@e=@ descendent
解释下descendent是element的另一种说法
},
"separators": {//编译规则
"descendent": "__",
"modifier": "--"
}
分别用@b ,@e,@m作为component, modifier, descendent的简写.编译成dist中的css时词与词之间的连接符为__或--来区分bem.
以btton为例:
@component-namespace el {
@b button {//button作为一个block
@m primary {//primary带有的样式 }
@e header {//作为元素的样式}
}
}
编译后的得到:
el-button{//button的基本样式}
el-button--primary {//主要的button按钮除了基本样式之外primary带有的样式 }
el-button__header{//头部元素的样式}