关于javascript:团队分享Bem规范调研及实践

49次阅读

共计 4804 个字符,预计需要花费 13 分钟才能阅读完成。

有幻想,有干货,微信搜寻【大迁世界】关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

背景

最近老大在保护他人的代码时,发现咱们团队写的款式各有种的想法及格调,这在后续保护会减少肯定的难度,所以老大决定对立款式的会名标准,所以就安顿我去调研及实际,上面是我调研的后果。

什么是 BEM 命名标准

BEM 由 Yandex 团队提出的一种前端 CSS 命名方法论。BEM 是 BlockElementModifier 的缩写,其中B 示意块(block)、E 示意元素(element)、M 示意修饰符(modifier)。

这三个局部通常应用 __-- 连贯。即:. 块__元素 -- 修饰符{}

  • Block:代表了一个独立的块级元素,能够了解为性能组件块。一个 Block 就是一个独立的区块,比方头部是个 block, 表单性能输入框是一个 block,block 可大可小。
  • Element:是 Block 的一部分不能独立来应用的,所有的 Element 都是与 Block 严密关联的。例如一个带有 icon 的输入框,那么 这个 icon 就是这个输入框 Block 的一个 Element,脱离了输入框的 Block 那么这个 icon 就没有意义。
  • Modifier:是用来润饰 Block 或 Element,示意 block 或者 element 在外观或行为上的扭转。例如,下面提到的输入框 Block,当鼠标悬停时边框高亮,那么这个高亮的成果就应该用 Modifier 来实现。

上图绿色表 block,蓝色示意 element,红色示意 modifier

为什么要用 BEM?

性能

CSS 引擎查找样式表,对每条规定都按从右到左的程序去匹配,以下这段代码看起来很快,实际上很慢。通常咱们会认为浏览器是这样工作的:找到惟一 ID 元素 ul-id —> 把款式利用到li 元素上。

事实上: 从右到左进行匹配,遍历页面上每个 li元素并确定其父元素

#ul-id li {}

所以不要让你的 css 超过三层。

语义化

BEM 的要害是光凭名字就能够通知其余开发者某个标记是用来干什么的。通过浏览 HTML 代码中的 class 属性,你就可能明确模块之间是如何关联的:有一些仅仅是组件,有一些则是这些组件的子孙或者是元素, 还有一些是组件的其余状态或者是修饰符。

惯例的命名法示例:

 <div class="article">
    <div class="body">
        <button class="button-primary"></button>
        <button class="button-success"></button>
    </div>
</div>

这种写法从 DOM 构造和类命名上能够理解每个元素的意义,但无奈明确其实在的层级关系。在 css 定义时,也必须依附层级选择器来限定束缚作用域,以防止跨组件的款式净化。

应用了 BEM 命名办法的示例:

<div class="article">
    <div class="article__body">
        <div class="tag"></div>
        <button class="article__button--primary"></button>
        <button class="article__button--success"></button>
    </div>
</div>

通过 BEM 命名形式,模块层级关系简略清晰,而且 css 书写上也不用作过多的层级抉择。

怎么用?

假如咱们要实现这样的一个卡片性能:

依据下面的设计图,咱们用 bem 形式来给对应 class 命名,如下所示:

<div class="card">
    <img class="card__img" src="./img.jpg" alt="">
    <div class="card__content">
        <ul class="card__list">
            <li class="card__item card__item--active"> 手机 </li>
            <li class="card__item"> 挪动市场 </li>
            <li class="card__item"> 科技 </li>
        </ul>
        <p class="card__desc"> 商化前端是一个很有生机的团队,能学到很多常识,你心动了吗?</p>
        <a class="card__link" href="#"> 具体内容 </a>
    </div>
</div>

对应的 CSS 构造:

.card{// 省略...}
.card__img{// 省略...}
.card__content {// 省略...}
.card__list{// 省略...}
.card__item {// 省略...}
.card__item--active {// 省略...}
.card__link{// 省略...}
.card__link:hover{// 省略...}

从下面的代码能够看出,咱们款式类没有一点嵌套关系,嵌套关系都以从命名的形式来代替。

这里刚开始应用 bem 的时候容易犯一个问题,就是把 ulli 的款式写成 card__content__listcard__content__list__item 因为这样更能体现层级的关系。

这有悖 BEM 命名标准,BEM 的命名中只蕴含三个局部,元素名只占其中一部分,所以不能呈现多个元素名的状况。这样的约定能够避免当层级很深命名过长的问题。

下面咱们每个款式都要写一遍 card,如果 card 换成一个比拟长的单词,这样也太简短了,这也是大家不太喜爱 bem 的一个起因,但这个 sassless 是很好的解决的,咱们能够用 & 示意根元素,下面在 less 或 sass 中能够改成如下构造:

.card{
  // 省略...
  &__img{// 省略...}
  &__content {// 省略...}
  &__list{// 省略...}
  &__item {// 省略...}
  &__item--active {// 省略...}
  &__link{// 省略...}
  &__link:hover{// 省略...}
}

插件的应用

eslint 校验相似,stylelint 也有一个配置文件 .stylelintrc.js(还有其余格局的,这里以js 文件为例)。

module.exports = {};

为了让小伙伴编写合乎 Bem 的标准,这里咱们应用 stylelint-selector-bem-pattern 插件,它联合了插件 postcss-bem-linter 的规定,可用于校验 BEM 命名标准。

module.exports = {
  plugins: ['stylelint-selector-bem-pattern'],
  "rules": {
       'plugin/selector-bem-pattern': {
          // 抉择 Preset Patterns,反对 suit 和 bem 两种,默认 suit 标准;// 不论哪种都须要手动指定,因为该插件未给源插件默认指定
          'preset': 'bem',
          /**
           * 自定义模式规定
           * 指定组合的选择器查看规定,其实就是指定 class 名称规定
           * 反对正则字符串、返回正则的函数、蕴含 2 个选项参数的对象等写法
           */
          componentSelectors: {
            // 只初始的选择器规定(能够了解为外层的 class 规定)initial: '^\\.{componentName}(?:__[-a-z]+)?(?:--[a-z]+)?$',
            // 能够了解为外层以内的选择器的规定,// 如果不指定,则跟 initial 同样的规定,// 留神这里配置的时候比下面少一个问号,// 是心愿内层就不应该只有 componentName 作为选择器了
            combined: '^\\.{componentName}(?:__[-a-z]+)(?:--[a-z]+)?$'
          },
          "utilitySelectors": "^\\.u-[a-z]+$",
          ignoreSelectors: ['^\\.el-', '/deep/', '>>>', '^\\.icon-'],
          ignoreCustomProperties: [],}
   }
}

配置实现后,为了能让 VsCode 给出谬误提醒,咱们须要在 VsCode 中增加 stylelint插件。

最初,就是 git commit 校验

// package.json
{
    "husky": {
        "hooks": {"pre-commit": "lint-staged"}
    },
   "lint-staged": {"*.{vue,ts,tsx,js,jsx}": "eslint --fix",
    "*.{vue,css,less,sass,scss}": "stylelint --fix"
  },
}

这里波及到 husky 的应用,如果不懂的,能够自行谷歌理解理具体的信息。

实战

配置实现后,咱们就须要入手验证一下了

首先,咱们须要定义一个上下文,这样插件才晓得对 CSS 进行校验。

比方咱们有如下的 html 构造:

<div class="form form--theme-xmas">
  <input class="form__input" />
  <input class="form__submit form__submit--disabled" type="submit" />
</form>

对应的 css 要这样写:

/** @define formWrapper */
.formWrapper{
  padding: 0 20px;
  box-sizing: border-box;
}
.formWrapper--line{display: none;}
.formWrapper__form-item{
  display: flex;
  align-items: center;
  margin-bottom: 20px;
}

这里 @define formWrapper 申明了一个 block formWrapper,示意款式必须是 formWrapper 结尾,否则报错。

如果有多个 block,咱们只有多个 @define 申明即可。

/** @define Foo */
.Foo {}

/** @define Bar */
.Bar {}

如果一个类不属于任何的 block,咱们又要怎么做,才不会导致 styleint 报错呢?这里咱们能够加 /** @end */ 示意 block 的完结。

/** @define form */
.form{display: flex;}
.form--theme-blue{text-align: center;}
/** @end */

.isActive{display: flex;}

如果咱们想疏忽对某块款式进行校验,能够应用上面的语法来疏忽:

/** @define MyComponent */

.MyComponent {display: flex;}

/* postcss-bem-linter: ignore */
.no-flexbox .Component {display: block;}

总结

BEM 最难的局部之一是明确作用域是从哪开始和到哪完结的,以及什么时候应用或不应用它。随着一直应用的教训积攒,你缓缓就会晓得怎么用,这些问题也不再是问题。技术无好坏,适合方最好。

参考:
https://www.jianshu.com/p/54b…
https://juejin.cn/post/684490…
https://segmentfault.com/a/11…
https://www.kancloud.cn/kancl…
https://juejin.cn/post/688530…

代码部署后可能存在的 BUG 没法实时晓得,预先为了解决这些 BUG,花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

交换

有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588… 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

正文完
 0