当前位置: 首页 > Web前端 > HTML

团队分享,Bem标准研究与实践

时间:2023-03-28 14:59:51 HTML

有梦想,有干货,微信搜索【大千世界】关注这位凌晨还在洗碗的洗碗智慧。本文已收录到GitHubhttps://github.com/qq449245884/xiaozhi,里面有完整的测试站点、资料和我的一线厂商访谈系列文章。背景最近老大在维护别人的代码的时候,发现我们团队写的样式有各种思路和风格,会增加后续维护的难度,所以老大决定统一会议名称的标准,所以他安排我考察和实践,以下是我的研究成果。什么是BEM命名规范BEM是Yandex团队提出的一种前端CSS命名规范。BEM是BlockElementModifier的缩写,其中B代表block,E代表element,M代表modifier。这三部分通常用__和--连接。即:.block__element--modifier{}Block:表示一个独立的块级元素,可以理解为功能组件块。Block是一个独立的块。比如表头是一个块,表单功能输入框是一个块。块可大可小。Element:是Block的一部分,不能独立使用。所有元素都与块密切相关。比如有一个带图标的输入框,那么这个图标就是输入框Block的一个Element,如果脱离了输入框的Block,图标就没有意义了。修饰符:用于修改块或元素,指示块或元素的外观或行为发生变化。比如上面提到的输入框Block的边框,当鼠标悬停在上面时,它的边框就会高亮,那么高亮效果就应该用Modifier来实现。上图中,绿色代表block,蓝色代表element,红色代表modifier。为什么要使用BEM?性能CSS引擎查找样式表并以从右到左的顺序匹配每个规则。下面的代码看起来很快,但实际上很慢。通常我们认为浏览器是这样工作的:找到唯一ID元素ul-id—>将样式应用于li元素。其实:从右往左匹配,遍历页面上每一个li元素,并确定其父元素#ul-idli{}所以你的css不要超过三层。语义BEM的关键在于名称本身就告诉其他开发人员标签的用途。通过浏览HTML代码中的class属性,您可以了解模块是如何关联的:有些只是组件,有些是这些组件的后代或元素,还有一些是组件符号的其他形式或装饰。一般命名示例:

这种写法可以从DOM结构和类命名上理解各个元素的含义,但无法明确其真正的层级关系。在定义css的时候,还必须依赖分层选择器来限制约束的范围,避免跨组件的样式污染。使用BEM命名方法的示例:
采用BEM命名方式,模块层级关系简单明了,无需在css中做过多层级选择写作。如何使用?假设我们要实现这样一个卡片功能:根据上面的设计图,我们使用bem方法命名对应的类,如下所示:手机移动市场技术商业化前端是一个很有活力的团队,可以学到很多东西的知识,你激动了吗?

详情对应的CSS结构:.card{//省略...}.card__img{//省略...}.card__content{//省略...}.card__list{//省略...}.card__item{//省略...}.card__item--active{//省略...}。card__link{//省略...}.card__link:hover{//省略...}从上面的代码可以看出,我们的style类完全没有嵌套关系,嵌套关系被slavenaming代替。这里刚开始使用bem的时候很容易出一个问题,就是把ul和li的样式写成card__content__list和card__content__list__item,因为这样更能体现层次关系。这违反了BEM命名约定。BEM命名只包含三部分,元素名只占一部分,所以元素名不能有多个。这样的约定可以防止层级很深时命名过长的问题。我们必须为上面的每个样式写卡片。如果将card换成更长的词,就太长了。这也是为什么人们不喜欢bem的原因之一,但是这个sass还是less是一个很好的解决方案。我们可以用&表示根元素,在less或sass中可以改为如下结构:.card{//省略...&__img{//省略...}&__content{//省略...}&__list{//省略...}&__item{//省略...}&__item--active{//省略...}&__link{//省略...}&__link:hover{//省略...}}plugin's和eslint验证类似,stylelint也有一个配置文件.stylelintrc.js(还有其他格式,这里以一个js文件为例)。模块.exports={};为了让小伙伴们写出符合Bem规范的规范,这里我们使用了stylelint-selector-bem-pattern插件,它结合了插件postcss-bem-linter的规则,可以用来验证BEM的命名约定。module.exports={plugins:['stylelint-selector-bem-pattern'],"rules":{'plugin/selector-bem-pattern':{//选择PresetPatterns,支持suit和bem,默认suitSpecification;//不管哪个都需要手动指定,因为插件默认没有为源插件指定'preset':'bem',/***自定义模式规则*指定组合的选择器检查规则,其实指定类名规则*支持正则字符串、返回正则表达式的函数、包含2个选项参数的对象等*/componentSelectors:{//只有初始选择器规则(可以理解为外部类规则)initial:'^\\.{componentName}(?:__[-a-z]+)?(?:--[a-z]+)?$',//可以理解为外层里面选择器的规则,//ifnotspecified,和initial一样的规则,//注意这里配置的时候比上面少了一个问号,//希望内层不要只有componentName作为选择器组合:'^\\.{componentName}(?:__[-a-z]+)(?:--[a-z]+)?$'},"utilitySelectors":"^\\.u-[a-z]+$",ignoreSelectors:['^\\.el-','/deep/','>>>','^\\.icon-'],ignoreCustomProperties:[],}}}配置完成后,为了让VsCode给出错误信息,我们需要在VsCode中添加sty在lelint插件的最后是gitcommitcheck//package.json{"husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"*.{vue,ts,tsx,js,jsx}":"eslint--fix","*.{vue,css,less,sass,scss}":"stylelint--fix"},}这涉及到husky的使用,不明白的可以自行谷歌了解详细信息。实际配置完成后,我们需要先进行验证。首先,我们需要定义一个上下文,以便插件知道要验证CSS。例如,我们有如下html结构:>/form>对应的css应该这样写:/**@defineformWrapper*/.formWrapper{padding:020px;box-sizing:border-box;}.??formWrapper--line{display:none;}.formWrapper__form-item{display:flex;对齐项目:居中;margin-bottom:20px;}这里@defineformWrapper声明了一个blockformWrapper,表示样式必须以formWrapper开头,否则会报错。如果有多个块,我们只需要多个@define声明。/**@defineFoo*/.Foo{}/**@defineBar*/.Bar{}如果一个class不属于任何block,怎么办才不会导致styleint报错呢?这里我们可以加上/**@end*/来表示块的结束。/**@defineform*/.form{display:flex;}.form--theme-blue{text-align:center;}/**@end*/.isActive{display:flex;}如果我们想ignore要验证一个样式块,可以使用以下语法来忽略:/**@defineMyComponent*/.MyComponent{display:flex;}/*postcss-bem-linter:ignore*/.no-flexbox.Component{display:block;}总结BEM最困难的部分之一是知道范围从哪里开始和结束,以及何时使用它。随着不断使用经验的积累,你会逐渐知道如何使用,这些问题将不再是问题。技术没有好坏之分,合适的才是最好的。参考: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...代码部署后可能存在的bug无法实时获知。之后为了解决这些BUG,花费了很多时间在日志调试上,顺便给大家推荐一个好用的BUG监控工具Fundebug。交流有梦想,有干货,微信搜索【大千世界】关注这位凌晨还在洗碗的洗碗智者。本文GitHubhttps://github.com/qq44924588...已收录,有完整的测试站点、资料和我的一线厂商访谈系列文章。