CSS常见模块化方案
- BEM(Block Element Modifier): BEM是一种流行的命名约定,它通过特定的命名规则来组织CSS类名,使得样式具有模块化、可重用性和可读性。BEM的命名规则是:
block__element--modifier
。
- block:表示一个独立的模块或组件。
- element:表示模块内的一个元素。
- modifier:表示模块或元素的某个状态或变体。
- CSS-in-JS: CSS-in-JS是一种技术,它允许将CSS代码写进JavaScript中,与组件紧密绑定。这样,样式的作用域自然就被限制在组件内部,常见的库有styled-components、emotion等。
- CSS Modules: CSS Modules是构建在CSS-in-JS理念之上的技术,它允许在组件级别本地化CSS类名,从而实现模块化。通过编译时生成唯一的类名,CSS Modules确保了样式的局部性。
- CSS预处理器(如Sass、Less、Stylus): 这些工具提供了变量、嵌套、混合(Mixins)、继承等功能,使得CSS更加模块化和可维护。
- 命名空间: 通过在类名前加上特定的前缀来创建命名空间,例如.ns-button、.ns-modal等,以此来避免全局命名冲突。
在Vue中,样式设置通常是在单文件组件的<style>
标签内完成。通过在<style>
标签上添加scoped
属性,可以轻松实现样式的局部作用域,确保样式仅应用于当前组件,从而避免全局污染。此外,Vue的单文件组件还支持less
、sass
等预处理器,以及深度集成的CSS Modules
功能。
Vue中的scoped属性的原理
Vue中的scoped
属性的原理是基于CSS的作用域隔离,它通过以下步骤实现:
- 生成唯一属性: Vue在编译组件时,会为每个使用了
scoped
的<style>
标签生成一个唯一的属性,比如data-v-f3f3eg9
。这个属性是随机生成的,确保了在全局范围内不会重复。 - 修改模板: Vue会遍历组件的模板,并将生成的唯一属性添加到模板中的所有元素上。这样,每个元素都会有一个对应的属性,用于标识它们属于当前的组件。
- 修改CSS选择器: Vue会修改
<style>
标签内的所有CSS选择器,为它们添加上面生成的唯一属性。这样,所有的CSS规则都会被限定只作用于带有这个唯一属性的元素。
<template>
<div class="example">Hello World</div>
</template>
<style scoped>
.example {
color: red;
}
</style>
编译后的结果
<div class="example" data-v-f3f3eg9>Hello World</div>
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
在上边的代码中, Vue编译器给组件中DOM元素和CSS各自都添加一个相同且唯一的属性选择器如data-v-f3f3eg9
。原始的CSS选择器.example
会被修改为.example[data-v-f3f3eg9]
,这样CSS规则就只会应用到带有data-v-f3f3eg9
属性的.example
类元素上。如果需要scoped
样式影响到子组件,可以使用>>>
、/deep/
或::v-deep
等深度选择器。Vue编译器会转换这些深度选择器,以便能够穿透组件边界。
注意点
使用 scoped 后,父组件的样式将不会渗透到子组件中。不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
- 子组件根节点受父组件scoped样式影响: 即使父组件的样式使用了scoped属性,子组件的根节点仍然可以被父组件的样式影响,因为子组件的根节点是在父组件的模板中定义的。Vue会为父组件的scoped样式添加的唯一属性也会应用到子组件的根节点上。
- 子组件的scoped样式: 子组件的scoped样式只会应用到子组件内部的元素,而不会影响到根节点以外的元素。这意味着子组件的根节点可以同时被父组件和子组件的scoped样式影响。