Team sharing, Bem standard research and Practice

There are dreams and dry goods. Wechat search [Daqian world] pays attention to this bowl washing wisdom who is still washing dishes in the early morning.
This article GitHub https://github.com/qq449245884/xiaozhi It has been included. There are complete test sites, materials and my series of articles for the interview of front-line large factories.

background

Recently, when the boss was maintaining other people's code, he found that the styles written by our team had different ideas and styles, which would increase some difficulty in subsequent maintenance. Therefore, the boss decided to unify the style of meeting name specification, so he arranged me to investigate and practice. The following is the results of my investigation.

What is the BEM naming convention

BEM is a front-end CSS naming methodology proposed by Yandex team. BEM is the abbreviation of BlockElementModifier, where B represents block, E represents element and M represents modifier.

These three parts are usually used__ Connect to. Namely:. Block__ Element -- modifier {}

  • Block: represents an independent block level element, which can be understood as a functional component block. A block is an independent block. For example, the header is a block, the form function input box is a block, and the block can be large or small.
  • Element: it is a part of a Block and cannot be used independently. All elements are closely related to the Block. For example, an input box with an icon is an element of the input box Block. If it is separated from the input box Block, the icon has no meaning.
  • Modifier: it is used to modify a Block or element, indicating the change in the appearance or behavior of the Block or element. For example, in the input box Block mentioned above, when the mouse hovers, the border is highlighted, then the highlighting effect should be realized by modifier.

In the above figure, the green table block, blue indicates element and red indicates modifier.

Why use BEM?

performance

The CSS engine looks up the style sheet and matches each rule from right to left. The following code looks fast, but it is actually very slow. We usually think that browsers work like this: find the unique ID element UL ID - > apply the style to the li element.

In fact: match from right to left, traverse each li element on the page and determine its parent element

#ul-id li {}

So don't let your css exceed three layers.

Semantic

The key to BEM is that the name alone can tell other developers what a tag is used for. By browsing the class attribute in HTML code, you can understand how modules are related: some are just components, some are descendants or elements of these components, and some are other forms or modifiers of components.

Examples of general nomenclature:

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

This writing method can understand the meaning of each element from the DOM structure and class naming, but it can not clarify its real hierarchical relationship. When defining css, you must also rely on level selectors to limit the scope of constraints to avoid style pollution across components.

Examples of using the BEM naming method:

<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>

Through the BEM naming method, the module hierarchical relationship is simple and clear, and there is no need to make too many hierarchical choices in css writing.

How to use it?

Suppose we want to realize such a card function:

According to the above design drawing, we name the corresponding class in bem, as shown below:

<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">mobile phone</li>
            <li class="card__item">Mobile market</li>
            <li class="card__item">science and technology</li>
        </ul>
        <p class="card__desc">The commercial front-end is a very dynamic team. Can you learn a lot of knowledge? Are you excited?</p>
        <a class="card__link" href="#"> details</a>
    </div>
</div>

Corresponding CSS structure:

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

As can be seen from the above code, our style class does not have any nested relationship, and the nested relationship is replaced by naming.

When using bem at the beginning, it is easy to make a problem that the styles of ul and li are written as card_content_list and card_content_list_item, because this can better reflect the hierarchical relationship.

This is contrary to the BEM naming standard. The naming of BEM only includes three parts, and the element name only accounts for one part. Therefore, multiple element names cannot occur. This convention can prevent the problem of too long naming when the level is very deep.

We need to write card for each style above. If card is replaced with a longer word, it will be too long. This is also one reason why we don't like bem, but this sass or less is a good solution. We can use & to represent the root element. In less or sass, it can be changed to the following structure:

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

Use of plug-ins

Similar to eslint verification, stylelint also has a configuration file. Stylelintrc.js (there are other formats, taking JS file as an example).

module.exports = {};

In order to let small partners write specifications that conform to Bem, we use stylelint-selector-bem-pattern Plug in, which combines plug-ins postcss-bem-linter Rules that can be used to verify the BEM naming convention.

module.exports = {
  plugins: [
    'stylelint-selector-bem-pattern'
  ],
  "rules": {
       'plugin/selector-bem-pattern': {
          // Select Preset Patterns, support suit and bem, and the default suit specification;
          // Either one needs to be specified manually because the plug-in does not specify it by default to the source plug-in
          'preset': 'bem',
          /**
           * Custom mode rules
           * Specifying the selector check rule of the combination is actually the rule of specifying the class name
           * Support regular strings, functions that return regular, objects with 2 option parameters, etc
           */
          componentSelectors: {
            // Only the initial selector rule (which can be understood as the outer class rule)
            initial: '^\\.{componentName}(?:__[-a-z]+)?(?:--[a-z]+)?$',
            // It can be understood as the rule of selector within the outer layer,
            // If not specified, the same rules as initial will apply,
            // Note that there is a question mark less than the above when configuring here,
            // It is hoped that the inner layer should not have only componentName as the selector
            combined: '^\\.{componentName}(?:__[-a-z]+)(?:--[a-z]+)?$'
          },
          "utilitySelectors": "^\\.u-[a-z]+$",
          ignoreSelectors: ['^\\.el-', '/deep/', '>>>', '^\\.icon-'],
          ignoreCustomProperties: [],
        }
   }
}

After configuration, in order to make VsCode give error prompt, we need to add stylelint plug-in to VsCode.

Finally, git commit verification

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

This involves the use of husky. If you don't understand it, you can google the detailed information by yourself.

actual combat

After the configuration is completed, we need to verify it

First, we need to define a context so that the plug-in knows to verify CSS.

For example, we have the following html structure:

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

The corresponding css should be written as follows:

/** @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;
}

Here @ define formWrapper declares a block formWrapper, indicating that the style must start with formWrapper, or an error will be reported.

If there are multiple block s, we only need multiple @ define declarations.

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

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

If a class does not belong to any block, what should we do to prevent styleint from reporting an error? Here we can add / * * @ end * / to indicate the end of the block.

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

.isActive{
  display: flex;
}

If we want to ignore the verification of a block style, we can use the following syntax to ignore it:

/** @define MyComponent */

.MyComponent {
  display: flex;
}

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

summary

One of the hardest parts of BEM is knowing where the scope starts and ends, and when to use it or not. With the accumulation of experience in continuous use, you will gradually know how to use it, and these problems are no longer problems. Technology is neither good nor bad, the right party is the best.

reference resources:
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...

The bugs that may exist after code deployment cannot be known in real time. Afterwards, in order to solve these bugs, we spent a lot of time on log debugging. By the way, we recommend a useful BUG monitoring tool Fundebug.

communication

There are dreams and dry goods. Wechat search [Daqian world] pays attention to this bowl washing wisdom who is still washing dishes in the early morning.

This article GitHub https://github.com/qq44924588... It has been included. There are complete test sites, materials and my series of articles for the interview of front-line large factories.

Tags: Javascript Front-end Vue.js

Posted on Tue, 30 Nov 2021 23:04:28 -0500 by JRS