BEM方法论以opencart中的贴纸为例



由于我更喜欢​​BEM方法论,因此当我开始使用opencart时,我立即遇到了可怕的事情,它们是嵌套的选择器。 他们无处不在! 从默认模板开始,以几乎所有模块和版权模板结尾。 为什么这样 我认为有很多原因:

  1. 默认情况下,Opencart是在嵌套选择器(模板和管理面板)上构建的。
  2. 使用opencart的大多数开发人员都是后端开发人员,他们只是采用了这种方法
  3. 标准opencart功能和author模块都附加了许多必要的类和id,并且出于各种原因,所有相同的后端开发人员及其追随者都不想更改任何内容并顺其自然。

我绝不想对后端开发人员说些不好的话,但是其中许多人实际上在前端甚至布局上都很薄弱。 该意见是基于与他们的交流,合作以及他们通常在主题opencart论坛上的活动而形成的。 我强调我的意思是opencart开发人员的利基市场。

我根据BEM方法(尽可能在opencart的框架内)从头开始制作模板,并且我可以自信地说,无论标记如何,任何模块都以半踢开头。 下面将要讨论的模块根本不需要任何校正,所需要做的只是简化它的工作,并实现在其他项目中重用它的可能性。 我以该模块为例,因为它非常简单,不需要被一堆额外的代码分散注意力,但是与此同时,它包含了BEM解决的所有问题。 这是一个真正的现有模块,并且有很多这样的模块,并且只有模板。 我相信一个战斗例子要比数百个抽象例子更好。

首先,我将描述问题实质 。 在一个家用opencart组件中,集成了一个贴纸模块。 它以指定角度显示所选贴纸:
左上/右上/左下/右下
没有贴纸选项,但最多有4个位置:



现在让我们看一下标记和样式:



我们看到的是:

  1. 所有贴纸均嵌入在图像块中。
  2. 尽管图像块在逻辑上被设计为存储产品的图像,但所有标签样式都与之相关,现在着眼于整个CSS,尤其是最后几行中的嵌套:

/*sticker*/ .image { position: relative; } .image .corner_0, .image .corner_1, .image .corner_2, .image .corner_3 { height: 57px; width: 58px; position: absolute; z-index: 998; } .image .corner_0 { left: 0px; top: 0px; } .image .corner_1 { right: 0px; top: 0px; } .image .corner_2 { left: 0px; bottom: 0px; } .image .corner_3 { right: 0px; bottom: 0px; } .box-product .image .corner_0 img, .box-product .image .corner_1 img, .box-product .image .corner_2 img, .box-product .image .corner_3 img { border: none; padding: 0px; } .box .box-product .image .corner_0 img, .box .box-product .image .corner_1 img, .box .box-product .image .corner_2 img, .box .box-product .image .corner_3 img { width: 60%; } 

如果.image .corner_2看起来更不被接受,那么.box .box-product .image .corner_2 img看起来并不那么乐观...总的来说,我们可以猜测到某个地方会有.box-product而没有父.box和使用了某些样式,但是在某些样式中与父样式一起使用,但是在这里我们面临许多问题:

  1. 如果将贴纸移到.image之外,则所有样式都会掉落,如果我们将.image放在另一个位置,则在不需要它们的地方应用.image样式。
  2. 如果您突然重命名图像,该图像在逻辑上不是贴纸或.box或.box-product的存储库,它们甚至更高,并且当然不说贴纸已附加,在任何情况下,我们都无法获得预期的结果。
  3. 如果我们想将.image.box-product放在一起怎么办? 再次,出问题了...
  4. 有很多重复的选择器,其中只有.corner_#更改,并且如果我们突然更改此嵌套或要将代码转移到另一个模板,我们将不得不在各处进行更改,并且仍然可能存在媒体查询,这只是浪费时间。
  5. 特异性增加。 一段时间后,这个问题总是很明显,并且经常落在那些没有创造出来的人的肩膀上。

那些熟悉BEM方法论的人早就意识到了这一点,而那些不熟悉的人,我想我遇到了不止一次。 让我们尝试解决这些问题。

由于主要任务之一是能够重复使用代码,因此我们无法像以前那样命名贴图的角,因为也许在另一个项目中,我们希望它们不在角上,而是在每一侧的中间或通常对齐,因此分别命名一个贴纸是合乎逻辑的,但是为了不依赖外部方块,请将我们的棍棒放在贴纸容器中,该容器可以是独立的方块,也可以是产品卡中任何方块的混合物。 结果:



在外部,我们得到了相同的结果,但是标记和样式现在不同了:

 /* stickers */ .stickers { position: relative; } .sticker { } .sticker_position_0 { position: absolute; left: 0px; top: 0px; } .sticker_position_1 { position: absolute; right: 0px; top: 0px; } .sticker_position_2 { position: absolute; left: 0px; bottom: 0px; } .sticker_position_3 { position: absolute; right: 0px; bottom: 0px; } .sticker__img { border: none; padding: 0; } 

如我之前所说, .stickers容器可以是独立的单元,也可以是产品卡中任何单元的组合。 在这种情况下,我们通过划分分配将其混合到.image块中。

每个贴纸都有一个.sticker类,其中包含所有贴纸共有的样式,例如大小。 但是,我们使用position键取出负责在修饰符中定位的样式:



注意事项:
.sticker可以作为元素.stickers
 <div class="stickers"> <div class="stickers__sticker sticker sticker_position_2"> <img class="sticker__img " src="#"> </div> </div> 
以及一个独立的点放置块,没有上下文标签

现在只要轻轻一按,您就可以在任何地方贴上贴纸了。 例如,您可以从图像中取出木棍,并应用于产品容器中的整个产品卡:



主要要点是进一步的操作将更加容易,并且将这些代码复制到另一个项目中后,该代码将立即开始工作,仅需使用必要的属性对其进行修改。

这些选择器仍然有一个未解决的问题,这些问题早已引起人们的注意:

 .box-product .image .corner_3 img {....} .box .box-product .image .corner_2 img {....} 

通常,我没有找到盒式产品来查看问题的背景,因此无法确定是否需要这样的选择器,但是BEM方法不会禁止嵌套(如果您不能没有嵌套的话)。 使用生成的标记,至少可以将选择器减少到2个类,这将允许与元素进行更精确的交互,而又不增加特定性,您可以通过按正确的顺序排列它们来重新定义或添加样式:

 .box-product .sticker__img {...} .box .sticker__img {...} 

结论


这是一小段代码,很有意义。

整理一个块足以使工作更轻松。 即使在一个完全启动的项目上,也可以实现更稳定的工作,甚至更多,因此您可以一次重写一个模块,从而使每个人的生活变得更轻松。

感谢所有读完本书的人,我希望我的文章对您有所帮助。

Source: https://habr.com/ru/post/zh-CN457016/


All Articles