问题背景
Vue中scoped
的原理主要是 通过为当前组件的模板添加一个独一无二的属性,然后在 CSS 选择器中添加这个属性,从而实现样式的局部作用域。
缺点
- 样式优先级问题
- 由于
scoped
通过添加唯一的属性来工作,这会增加选择器的特异性,可能导致由于特异性不同而出现样式优先级问题。例如:通过在父组件中设置样式类,统一控制父子组件的样式。
- 由于
- 无法跨组件边界工作
scoped
无法控制其他组件的样式,包括子组件。vue
提供了解决方案,可以使用:deep()
包括需要穿透的类,达到影响子元素的效果。不过若是频繁使用:deep()
,影响代码美观和整洁度是必然的。
- 性能问题
- 使用
scoped
可能会导致性能问题,因为浏览器在渲染时必须查找和匹配这些唯一的属性。
- 使用
解决方案
有BEM
命名策略和CSS Module
两种方案:
-
BEM
结合工具函数和scss
预处理函数,可以极大地减轻应用的心智负担,比较典型的ElementPlus
中就有BEM
命名策略的应用。 -
CSS Module
我更多的是在React
项目中使用
BEM 命名策略
什么是 BEM 命名规范
Bem 是块(block)、元素(element)、修饰符(modifier)的简写,由 Yandex 团队提出的一种前端 CSS 命名方法论。
- 中划线 :仅作为连字符使用,表示某个块或者某个子元素的多单词之间的连接记号。
__ 双下划线:双下划线用来连接块和块的子元素
_ 单下划线:单下划线用来描述一个块或者块的子元素的一种状态
BEM的命名规则
命名约定的模式如下:
.block{}
.block__element{}
.block--modifier{}
BEM解决问题的思路
由于项目开发中,每个组件都是唯一无二的,其名字也是独一无二的,组件内部元素的名字都加上组件名,并用元素的名字作为选择器,自然组件内的样式就不会与组件外的样式冲突了。
BEM的命名规则:block-name__element-name--modifier-name,也就是模块名 + 元素名 + 修饰器名。
element-ui中 BEM 方法的使用
首先来看一个bem命名示例:
.el-message-box{}
.el-message-box__header{}
.el-message-box__header--active{}
如果scss的话,那么可以写成:
.el-message-box {
&__header' {
&--active {
}
}
}