BEM 命名规范:高德地图实战

在前端开发中,命名规范的使用对项目的可维护性、可读性以及扩展性至关重要。本文将介绍 BEM (Block, Element, Modifier) 命名规范,分析一个实际项目的代码片段。

BEM 命名规范

BEM 是一种 CSS 命名方法论,旨在提高代码的可维护性和复用性。通过使用 Block(区块)、Element(子元素)和 Modifier(修饰符),开发者能够更好地管理样式。

  • Block(区块) : 页面中的独立功能部分或组件,例如 .page.search-bar.navigation 等。
  • Element(子元素) : Block 的组成部分,与 Block 关联且不能单独存在。例如 .search-bar__input 表示 search-bar 这个 Block 的输入框子元素。
  • Modifier(修饰符) : 用于表示 Block 或 Element 的不同状态或版本。例如 .navigation__icon--primary.navigation__icon--default 分别表示图标的两种不同样式。

命名示例

html 复制代码
<div class="card">
  <div class="card__header">
    <h2 class="card__title">卡片标题</h2>
    <button class="card__button card__button--primary">主要按钮</button>
  </div>
  <div class="card__body">
    <p class="card__text">这是卡片的主体内容。</p>
  </div>
  <div class="card__footer">
    <a href="#" class="card__link">更多信息</a>
  </div>
</div>
  • Block.card 是一个块(block),代表整个卡片组件。

  • Element.card__header, .card__title, .card__button, .card__body, .card__text, .card__footer, .card__link 是元素(element),它们是卡片块的一部分。

  • Modifier.card__button--primary 是修饰符(modifier),用于修改 .card__button 的样式。

使用 BEM 命名规范,可以避免样式冲突,并且能够快速理解每个类的作用,提高开发效率。

实战分析

画图分析

现在我们来实战一下高德地图的导航栏,整体为下面这样,我们先看图分析

首先是page是一个块(block),再把它拆分成两部分:page__headpage__body两个元素(element)

接着再把page__head和page__body细分:

  • page__head

    1. page__head中有search-bar块
    2. search-bar块中有search-bar__input和search-bar__icon元素
  • page__body

    1. page__body中有navigation块
    2. navigation块中有navigation__item元素
    3. navigation__item元素中又有navigation__icon元素和navigation__text元素

以下是完整的代码示例:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高铁站页面</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            outline: 0;
        }

        body, html {
            height: 100%;
            -webkit-tap-highlight-color: transparent;
        }

        body {
            font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
        }

        .page {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
            overflow-scrolling: touch;
            padding: 10px;
            background-color: #f9f9f9;
        }

        .page__header {
            padding: 10px;
        }

        .search-bar {
            display: flex;
            align-items: center;
            height: 40px;
            border-radius: 20px;
            background-color: #fff;
            box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
        }

        .search-bar__icon {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0 10px;
        }

        .search-bar__icon-image {
            width: 20px;
            height: 20px;
        }

        .search-bar__input {
            flex-grow: 1;
            height: 100%;
            border: none;
            border-radius: 20px;
            padding: 0 10px;
            font-size: 16px;
            outline: none;
        }

        .page__body {
            display: flex;
            justify-content: space-around;
            margin-top: 20px;
        }

        .navigation__item {
            text-align: center;
            text-decoration: none;
        }

        .navigation__icon {
            width: 50px;
            height: 50px;
        }

        .navigation__text {
            margin-top: 5px;
            font-size: 14px;
            color: #333;
        }
    </style>
</head>
<body>
    <div class="page">
        <div class="page__header">
            <div class="search-bar">
                <span class="search-bar__icon">
                    <img src="img/sousuo.png" class="search-bar__icon-image">
                </span>
                <input class="search-bar__input" type="search" placeholder="高铁站">
                <a href="#" class="search-bar__icon">
                    <img src="img/iconfontscan.png" class="search-bar__icon-image">
                </a>
                <a href="#" class="search-bar__icon">
                    <img src="img/01.png" class="search-bar__icon-image">
                </a>
            </div>
        </div>
        <div class="page__body">
            <a href="#" class="navigation__item">
                <img src="img/buhang.png" class="navigation__icon">
                <div class="navigation__text">步行</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/gongjiao.png" class="navigation__icon">
                <div class="navigation__text">公交</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/a-jiache_huaban1.png" class="navigation__icon">
                <div class="navigation__text">驾车</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/tuisongtixing.png" class="navigation__icon">
                <div class="navigation__text">打车</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/yuding_jiudianicon.png" class="navigation__icon">
                <div class="navigation__text">订酒店</div>
            </a>
        </div>
    </div>
</body>
</html>

代码分析

  1. Block 定义:

    • .page 是页面的最外层容器,包含了整个页面内容。
    • .search-bar 是搜索栏区域,负责搜索功能的展示。
    • .navigation 是导航区域,包含多个导航选项。
  2. Element 定义:

    • .page__headerpage Block 的头部部分。
    • .search-bar__iconsearch-bar Block 中的图标元素,标识搜索按钮或其他功能。
    • .search-bar__inputsearch-bar Block 中的输入框。
    • .navigation__itemnavigation Block 中的单个导航项。
    • .navigation__icon.navigation__text 分别表示导航项中的图标和文本。
  3. Modifier 应用:

    • 在本示例中没有使用修饰符(Modifier),但可以想象当某个导航项被激活或处于不同状态时,可以通过 navigation__item_activenavigation__icon_primary 等修饰符来控制样式。

结语

通过 BEM 命名规范,可以显著提高代码的可读性、可维护性以及扩展性。在实际项目中,BEM 的规范不仅有助于团队协作,同时也减少了样式冲突,保证了项目的一致性。对于新手来说,尽量在取类名时考虑元素间的关联性,并遵循 BEM 规则,将为日后的开发与维护带来极大便利。

相关推荐
一个处女座的程序猿O(∩_∩)O1 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink4 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者6 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-6 小时前
验证码机制
前端·后端
燃先生._.7 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖8 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
唯之为之8 小时前
巧用mask属性创建一个纯CSS图标库
css·svg
m0_748235248 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240259 小时前
前端如何检测用户登录状态是否过期
前端