BEM-实战淘宝订单模块

3,326 阅读5分钟

1. 什么是BEM?

BEM是由Yandex公司推出的一套CSS命名规范,官方是这么描述它的:

BEM是一种让你可以快速开发网站并对此进行多年维护的技术。

一开始,Yandex公司推出的BEM,包括了规范以及其配套构建工具。如今提到的BEM主要是指其中的规范,在BEM最新的推广页中,对其的描述为:

BEM是一种命名方法,能够帮助你在前端开发中实现可复用的组件和代码共享。

2. BEM 命名规范

BEM就是块(block)、元素(element)、修饰符(modifier)的缩写,利用不同的区块,功能及样式来给元素命名。

BEM 命名约定模式

  • B:(block)具有自身意义的独立实体。

可以是一个块级元素,可以理解为组件块,比如头部是个block,内容也是block,一个block可能由几个子block组成。例子header container menu checkbox input

  • E:(element)块的一部分,没有独立的含义,并且在语义上与其块相关联。

element是block的一部分,完成某种功能,element依赖于block,比如在logo中,img是logo的一个element,在菜单中,菜单项是菜单的一个element。

  • M:(modeifier)块或元素上的标志。使用它们来更改外观或行为。

modifier代表block的不同状态或不同版本。比如active on

上面介绍了BEM分别是什么,那我们该如何连接他们呢?

.block { }
.block__element { }
.block--modifier{ }

其中

  • block 代表了更高级别的抽象或组件。
  • block__element 代表.block的后代,用于形成一个完整的.block的整体。
  • block–modifier代表.block的不同状态或不同版本。

下面我们来看个例子:
weui-primary_loading__dot:库名-组件_状态__元素名
库名:一般是各公司约定俗成的项目名或公司名。这里代表微信。
组件:一般用来创建单独的css来修饰特定的标签。
状态:一般以标签处于的状态或者可以进行交互的效果命名,这个例子可以表示正在加载中状态的样式
元素名:一般以标签作用描述命名。

3. BEM命名的好处

  • BEM的关键是光凭名字就可以告诉其他开发者某个标记是用来干什么的。  通过浏览HTML代码中的class属性,你就能够明白模块之间是如何关联的:有一些仅仅是组件,有一些则是这些组件的子孙或者是元素,还有一些是组件的其他形态或者是修饰符。
  • 更加模块化。 块样式永远不依赖于页面上的其他元素,因此你不会遇到级联问题。你还可以将已完成项目中的块转移到新项目。
  • 具有可重用性。 以不同方式组合独立块,并智能地重用它们,减少了你必须维护的CSS代码量。有了一套样式指南,你可以构建一个块库,使你的CSS超级有效。

4. 项目实战-淘宝订单

说了这么多,让我们自己动手来实践一下,用前面介绍到了BEM命名法来写一下淘宝订单结构吧~

Screenshot_20220409_142727_com.taobao.taobao_edit.jpg

首先我们来分析一下:

  • 这整个功能模块是淘宝页面的一小个功能部分,所以我们可以把这整个功能模块看作一个块(block),我们给他起名叫:tb-order
  • 在这整个块里分上下两个部分(element),上部分我们起名为:tb-order__hd;下部分叫:tb-order__bd
  • 在下面的部分中,分为5个小部分,我们给他起名为:tb-order__item ;这每个小部分中都有一个小圆点的元素,代表着当前各个页面情况的一个数量,比如待评价数量是2。我们在这给他起名:tb__pointer ;当它有数量的时候才进行显示,这时我们给他添加上状态(modefier):tb__pointer_on

1.png

分析到这,下面我们开始上代码:

<div class="tb-order">
        <div class="tb-order__hd">
            <span class="tb__title">我的订单</span>
            <span class="tb__more">全部 ></span>
        </div>
        <div class="tb-order__bd">
            <a href="#" class="tb-order__item">
                <span>
                    <span class="iconfont icon-31daifukuan"></span>
                    <span class="tb__pointer"></span>
                </span>
                <p class="tb__desc">待付款</p>
            </a>
            <a href="#" class="tb-order__item">
                <span>
                    <span class="iconfont icon-daifahuo"></span>
                    <span class="tb__pointer"></span>
                </span>
                <p class="tb__desc">待发货</p>
            </a>
            <a href="#" class="tb-order__item">
                <span>
                    <span class="iconfont icon-31daishouhuo"></span>
                    <span class="tb__pointer tb__pointer_on">2</span>
                </span>
                <p class="tb__desc">待收货</p>
            </a>
            <a href="#" class="tb-order__item">
                <span>
                    <span class="iconfont icon-xiaoxi"></span>
                    <span class="tb__pointer tb__pointer_on">8</span>
                </span>
                <p class="tb__desc">待评价</p>
            </a>
            <a href="#" class="tb-order__item">
                <span>
                    <span class="iconfont icon-tuikuantuihuo"></span>
                    <span class="tb__pointer"></span>
                </span>
                <p class="tb__desc">退款/售后</p>
            </a>
        </div>
 </div>

接下来完成css样式:

*{
    margin:0;
    padding: 0;
}
a{
    text-decoration: none;
}
body{
    background-color: #5b80d7;
    letter-spacing: 1px;
}
.tb-order{
    width:95%;
    margin:10px auto;
    background-color: white;
    border-radius: 20px;
}
.tb-order__hd{
    height:63px;
    padding:0 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.tb__title{
    font-size: 20px;
    font-weight:bold;
    /* line-height:63px; */
}
.tb__more{
    font-size:16px;
    color:gray;
}
.tb-order__bd{
    height:84px;
    display: flex;
    justify-content: space-around;
}
.tb-order__item{
    width:20%;
    text-align: center;
    line-height:2em;
    color:black;
    position: relative;
}
.iconfont{
    font-size: 30px;
    font-weight: 550;
}
.tb__desc{
    font-size: 14px;
}
.tb__pointer{
    width:22px;
    height:22px;
    position: absolute;
    display: inline-block;
    color:white;
    top:-9px;
    right:18px;
    border-radius: 50%;
    line-height: 22px;
    font-size:11px;
    font-weight: 550;
}
.tb__pointer_on{
   background-color: #ff7302;
}

最后外面做出来的结果就是这样子啦:

2.png

上图图标皆来自阿里图标库: iconfont-阿里巴巴矢量图标库
使用方式为下载代码方法,从上面网址下载。然后将其以css方式引入,使用类名进行添加。

5. 个人总结

  • 在学习BEM之前,我给每个组件起名都是基于对应的英文,写完html之后在添加css样式的时候就会有一种比较混乱的感觉。使用BEM之后感觉层次关系清晰了很多,我可以通过类名知道两个class之间的关系,另外还增加了代码的可复用性,减少了许多代码量。
  • 使用BEM起名可能会导致我们输入很长的文本(大部分编辑器都有自动补全功能,而且gzip压缩将会让我们消除对文件体积的担忧),但是它依旧强大。并且对于某些在该块(block)中是唯一存在的元素时,我们可以省略一些写它。比如上面例子中,在tb-order__hd内部有一个标题元素,它在整个模块中是唯一的,所以我们可以直接写成tb__title

6. 相关参考


getbem.com\