前端面试:BEM命名法实现抖音主页信息栏和功能栏

241 阅读6分钟

前言:

在面试中,关于BEM命名法的问题很常见,尤其是对于前端开发岗位。面试官可能会通过多种方式来评估我们对BEM的理解和实际应用能力。如:

问题: 你能解释一下什么是BEM命名法吗?它解决了前端开发中的哪些问题?

问题: 给定一个页面组件(如导航栏),请用BEM命名法来设计其CSS类名结构。

问题: 在一个复杂的组件中,如何使用BEM有效地管理嵌套层级和避免类名过长的问题?

......等等等等,接下来在这里我们讲解BEM命名规范和实现一个大厂前端案例。

BEM命名

BEM(Block Element Modifier)是一种国际上广泛应用的前端开发命名方法论,主要用于提高CSS的可维护性和可重用性。这一方法由Yandex团队提出,旨在通过明确的命名规则来组织和管理HTML和CSS中的组件。BEM命名法的核心理念是将用户界面拆分成基本的逻辑单元,并清晰地定义它们之间的关系。

Block(块):

表示一个独立的、可复用的组件或一个页面区域,具有明确的功能和语义。例如,header、menu 或 form 都可以是一个块。

Element(元素):

是块的一部分,没有独立的意义,只能在特定块的上下文中使用。元素的名称总是与它的块相关联,通过双下划线__连接。例如,header__logo 或 menu__item。

Modifier(修饰符):

用于描述块或元素的不同状态、版本或附加特性。修饰符通过双中划线--与块或元素的名称相连。修饰符可以改变块或元素的外观或行为,如 button--primary 或 list__item--active。

  BEM命名法的优势在于它强制执行了一种结构化的、自我解释的命名模式,这有助于开发者理解代码结构,减少样式间的意外冲突,并使得代码易于维护和团队协作。由于其强调模块化和可维护性,BEM成为了许多大型项目和框架的首选命名约定。

 

实现抖音主页页面 信息栏和功能栏

抖音主页功能选项页面在ipad中打开时是可以将全部展开的,而在手机移动端是不能全部展开,但是能左右滑动查看。

image.png

这里我们将用一段代码,还原出在两个不同客户端的界面效果,同时使用BEM命名规范代码书写,进行创建更贴近大厂实际开发的项目。

这里我们先分析页面结构。

image.png

页面主体分为两个大模块info和tab,然后info中又有个人签名signature和地区和添加个人其他信息模块home;tab栏中有单个项目item,item上半部分是ico图标,下半部分是title文字说明。有了这些信息的提取我们的结构就出来了

*<!-- 个人块-信息元素 -->*
  <div class="dy-person-info">
    *<!-- 个性签名 -->*
    <div class="dy-person-info_signature">祝你开心</div>
    *<!-- 地址 -->*
    <div class="dy-person-info_home">中国澳门</div>
    <div class="dy-person-info_home">+年龄学校等标签</div>
  </div>

  *<!-- 栏目块 -->*
  <div class="dy-tab">
    *<!-- 栏目块-单个项目 -->*
    <div class="dy-tab-item">
      *<!-- 图标 -->*
      <div class="dy-tab-item_icon iconfont icon-gouwuche"></div>
      *<!-- 标题 -->*
      <div class="dy-tab-item_title">抖音商城</div>
    </div>
</div>

 

将结构设计倾斜命名规范后我们开始着手CSS排版:

  * {
        margin: 0;
        padding: 0;
        outline: 0; */*轮廓 不同的浏览器不一样*/*
        box-sizing: border-box;
    }
    .dy-person-info{
      width: 100%;
    }
    .dy-person-info_signature{
      margin: 20px;
      font-size: 20px;
    }
    .dy-person-info_home{
      display: inline;
      margin-left: 20px;
      font-size: 20px;
      background-color: rgb(152, 151, 151);
      -webkit-user-select: none;
      user-select: none;
    }
    .dy-tab{
      display: flex;
      margin-top: 20px;
      overflow-x: scroll;
      padding-right: calc(17px + env(safe-area-inset-right));
    }
    */* 隐藏滚动条 */*
    .dy-tab::-webkit-scrollbar {
      width: 0; */* 设置宽度为0隐藏水平滚动条 */*
      height: 0; */* 如果需要隐藏垂直滚动条,设置高度为0 */*
      }
      .dy-tab-item{
      width: 100px;
      text-align: center;
      -webkit-user-select: none;
      user-select: none;
    }
    .dy-tab-item + .dy-tab-item{
      margin-left: 20px;
    }
    .dy-tab-item_icon{
      font-size: 40px;
      font-weight: 400;
    }
    .dy-tab-item_title{
      width: 120px;
      font-size: 20px;
      font-weight: 400;
    }

这里的CSS样式我们不细讲,但是这里要提出两个重要的样式:

 padding-right: calc(17px + env(safe-area-inset-right));

 -webkit-user-select: none;

 user-select: none;

有没有大佬知道这是什么操作。

其实一般的项目而言,着几个属性加不加上并不会影响项目,但是对于抖音这种超级软件,它的用户体验感一定是要被优化到极致的。

padding-right: calc(17px + env(safe-area-inset-right))

这是为苹果用户专门添加的 ,是为了处理移动设备上(尤其是iPhone和iPad等苹果设备)由于屏幕边缘的圆角设计和顶部的刘海(或底部的Home Indicator)导致的可触控区域减少的问题。这是所谓的“安全区域”概念。

-webkit-user-select: none; user-select: none;

是为防止长按时会弹出复制文字的效果,例如当你手湿湿的时候去触碰手机,或者是水滴在手机上,形成的误触,弹出的复制文字效果是非常降低用户的体验感的。就像这一样的

image.png

如果使用-webkit-user-select: none和user-select: none;之后便不会再出现这个效果了。

那为什么有两个样式属性呢,这也是大厂级项目的精细之处:

user-select: none;是chrome推出的实验属性一般只能在近些年的手机上起作用。 而-webkit-user-select: none;是已经早就被推广的属性,对于很久以前的手机也是适用的。 所以有没有感受到来自大厂为提高用户体验的细致。

 

最后把代码全贴:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./download/font_4563834_ah9gfiyordj/iconfont.css">
  <title>Document</title>
  <style>
    * {
        margin: 0;
        padding: 0;
        outline: 0; */*轮廓 不同的浏览器不一样*/*
        box-sizing: border-box;
    }
    .dy-person-info{
      width: 100%;
    }
    .dy-person-info_signature{
      margin: 20px;
      font-size: 20px;
    }
    .dy-person-info_home{
      display: inline;
      margin-left: 20px;
      font-size: 20px;
      background-color: rgb(152, 151, 151);
      -webkit-user-select: none;
      user-select: none; */*防止长按弹出复制等等select*/*
    }
    .dy-tab{
      display: flex;
      margin-top: 20px;
      overflow-x: scroll;
      */* 考虑到iOS边框安全区域 */*
      padding-right: calc(17px + env(safe-area-inset-right));
    }
    */* 隐藏滚动条 */*
    .dy-tab::-webkit-scrollbar {
      width: 0; */* 设置宽度为0隐藏水平滚动条 */*
      height: 0; */* 如果需要隐藏垂直滚动条,设置高度为0 */*
      }
      .dy-tab-item{
      width: 100px;
      text-align: center;
      -webkit-user-select: none;
      user-select: none; */*防止长按弹出复制等等select*/*
    }
    .dy-tab-item + .dy-tab-item{
      margin-left: 20px;
    }
    .dy-tab-item_icon{
      font-size: 40px;
      font-weight: 400;
    }
    .dy-tab-item_title{
      width: 120px;
      font-size: 20px;
      font-weight: 400;
    }
  </style>
</head>

<body>

  *<!-- 个人块-信息元素 -->*
  <div class="dy-person-info">
    *<!-- 个性签名 -->*
    <div class="dy-person-info_signature">祝你开心</div>
    *<!-- 地址,+标签 -->*
    <div class="dy-person-info_home">中国澳门</div>
    <div class="dy-person-info_home">+年龄学校等标签</div>
  </div>

  *<!-- 栏目块 -->*
  <div class="dy-tab">
    *<!-- 栏目块-单个项目 -->*
    <div class="dy-tab-item">
      *<!-- 图标 -->*
      <div class="dy-tab-item_icon iconfont icon-gouwuche"></div>
      *<!-- 标题 -->*
      <div class="dy-tab-item_title">抖音商城</div>
    </div>

    <div class="dy-tab-item">
      <div class="dy-tab-item_icon iconfont icon-shizhong"></div>
      <div class="dy-tab-item_title">观看历史</div>
    </div>


    <div class="dy-tab-item">
      <div class="dy-tab-item_icon iconfont icon-shu"></div>
      <div class="dy-tab-item_title">我的读书</div>
    </div>

    <div class="dy-tab-item">
      <div class="dy-tab-item_icon iconfont icon-qianbao"></div>
      <div class="dy-tab-item_title">我的钱包</div>
    </div>

    <div class="dy-tab-item">
      <div class="dy-tab-item_icon iconfont icon-lianxiren"></div>
      <div class="dy-tab-item_title">经常访问的人</div>
    </div>

    <div class="dy-tab-item">
      <div class="dy-tab-item_icon iconfont icon-yinle"></div>
      <div class="dy-tab-item_title">我的音乐</div>
    </div>

    <div class="dy-tab-item">
      <div class="dy-tab-item_icon iconfont icon-gengduo"></div>
      <div class="dy-tab-item_title">查看更多</div>
    </div>

  </div>
</body>
</html>

效果图:

image.png  

这里移动端模式下是可以滑动的,图片演示不出来,大家可以跑一下去试试

image.png

image.png

总结

顶级大厂做出来的产品,用户体验感是非常看重的,不论多小的细节一定都会做到极致。而对于内部代码的书写也是有着一套命名书写规范,在提高团队合作效率的同时也提升了代码的可读性和可维护性。