前言✍️
- 最近在搭自己的组件库,关于
CSS
预处理器用的是SCSS
。 - 对于样式的命名使用了
BEM
,借此机会分享一下。
怎么命名🔥
样式命名有多难
- 我以前觉得这是一个特别特别难的问题,这难的有恐怖呢,这就像产品让我做一个页面但没有设计图甚至原型图只是几个框框的情况下让我做的特别好看,色彩特别鲜艳一样,真是有(tian)点(da)困(lei)难(pi)🤏。
- 大家有没有遇到一种情况就是再写一个模块的时候它的内容给他样式命名
container
,那他的左边内容呢?右边内容呢?left-container
?right-container
?如果内容里面还有内容呢,原谅我英语不好,我还是会想用container
,要疯🤷♂️。 class
既要表达清楚这个样式代表什么又要不能有重复,样式重复的后果大家懂的都懂,所以我才说这对大部分前端来说是挺难的一个问题,但对一小部分前端程序员来说根本不值一提,为什么这么说呢?因为我遇见过名字按顺序one
,two
和three
来排列的class
名,我想这可能对他们来说不算什么事吧🤦♂️。- 开个玩笑,在正常情况下,我们对样式进行命名的时候都会去查对应模块的英文来进行命名(英文好的当我没说),起一个独一无二的名字。
- 但事实上我们不能保证我们"当时认为独一无二的名字"就是"独一无二的",当我们给一个tab加动态时可能会用到
actived
来代表被激活
被选中
,用了这个之后本能的其他的模块动态还是会想用这个名字actived
,如果有同感的可以留个赞了,说明我们是一类人哈哈哈😵。 - 有的同学可能会说,哎呀能跑就行不冲突就行反正客户又不会看你源码管你写的好不好看,但试想一下如果这个项目不是你一个人开发呢,当涉及到更大、更复杂的项目时,你如何组织代码是提高效率的关键!如果你提桶了之后轮到别人接手呢?别人看着你的代码就会跟别人抱怨:"看!这人写的什么屎山!" 是不是你曾经也这样吐槽过别人呢🙇。
关于BEM🌊
BEM是什么
BEM
—Block Element Modifier
是一种帮助您在前端开发中创建可重用组件和代码共享的方法,由Yandex
团队提出的一种前端CSS
命名方法论。- 所谓
BEM
说白了就是把样式按照B
E
M
三种来进行命名。 - BEM:
- B -
Block
一个独立的模块,一个本身就有意义的独立实体 比如:header
、menu
、container
- E -
Element
元素,块的一部分但是自身没有独立的含义 比如:header title
、container input
- M -
Modifier
修饰符,块或者元素的一些状态或者属性标志 比如:small
、checked
BEM使用
- 知道了
BEM
的基本概念后接下来就是使用了,上面我也说了,说白了BEM
也就是把三个连接在一起组成一个class
名,那怎么连接他们三呢? BEM
提出的一个概念是用连接符号来表达,它并不规定必须用什么连接符,但规定用不同连接符做团队内约定区分BEM 3类元素。B
其实可以理解成一个模块,就比如Element
的el-button
、Ant Design
的ant-btn
。E
的连接用官方的方式就是块名称加两个下划线加元素名称构成(__
)就比如Element
的el-radio__input
。M
的连接用官方的方式就是.block__elem--mod
,就比如Element
的el-button--small
、vant
的van-button--danger
。
BEM的好处
- 可以发现很多开源优秀的组件库都是用的BEM规范来命名,那为什么会这么受欢迎呢?
- 要知道我们用一个技术或者框架或者规范目的都是只有一个,让自己更舒服,就好像编辑器装插件,不用原生
js
开发而用框架开发一个道理。 方便查看
BEM
可以让开发人员在样式命名上就知道这个样式属于哪里,从名字就可以知道某个标记的含义,假设一个样式命名left-content
,光是找这个样式在哪里就已经很麻烦了。结构明了
在我们用scss
和less
预处理器的时候都习惯嵌套很多层,但有了BEM
命名后模块层级关系简单清晰,而且css
书写上也不必作过多的层级选择。可复用性
在写了一个元素的样式后需要对他的修饰符进行拼接样式修改,我们在scss
中可以使用@mixin
做些处理拼接E
和M
放到公共的scss
中别的地方再进行复用,就比如element
的mixins配置。
示例
说了这么多光看文字也烦了吧,还是放个简单的代码示例出来大家品吧,下面是一个按钮的组件封装。
<template> <button class="zl-button" :class="[ type ? 'zl-button--' + type : '', size ? 'zl-button--' + size : '' ]" type="button" > <slot /> </button> </template> <script> export default { name: 'ZlButton', props: { type: { validator (value) { return oneOf(value, ['default', 'primary', 'info', 'success', 'warning', 'danger']); }, type: String, default: 'default' }, size:{ validator (value) { return oneOf(value, ['','medium', 'small', 'mini']); }, type: String, default: '' } } }; </script> 复制代码
zl-button
可以看到这里用了B
的连接。zl-button--small
可以看到这里用了B
+M
中间用--
连接起来来代表块和修饰符连接。
写在最后👋
- 对于样式的规范其实也没有那么难,只是平时为了追求速度而放弃了规范,实际上如果时间允许的话还是用主流的规范来约束自己不让自己的代码变成别人口中的屎山。
- 如果您觉得这篇文章有帮助到您的的话不妨🍉关注+点赞+收藏+评论+转发🍉支持一下哟~~😛