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樣式影響。