前言
我們在用 vue 開發項目時,在給當前組件中的元素設置樣式,為了不污染全局樣式,一般會在當前組件的 <style>
標簽中增加 scoped 屬性,表明 CSS 只作用於當前組件中的元素。
實現原理
按 vue 官方解釋,scoped 是通過使用 PostCSS 來實現以下轉換,以達到不污染全局樣式。
<style scoped> .example { color: red; } </style> <template> <div class="example">hi</div> </template>
轉換為:
<style> .example[data-v-f3f3eg9] { color: red; } </style> <template> <div class="example" data-v-f3f3eg9>hi</div> </template>
分析后可知,PostCSS 處理組件 scoped 樣式時,給 HTML 的 DOM 節點加一個不重復屬性 data-v-f3f3eg9 標志唯一性。如果組件內部還有組件,只會給當前的組件增加類似屬性,不影響組件內部引用的組件。
深度作用選擇器
在使用 scoped 屬性后,達到了樣式的組件隔離作用,但是如果引用它的父組件,想修改/增加其樣式時,只能通過深度作用選擇器來實現。
>>> 操作符:
<style scoped> .a >>> .b { /* ... */ } </style>
有些像 less、sass 之類的 css 預處理語言,無法正確解析 >>>。我們可以使用 /deep/ 操作符取而代之。
/deep/ 操作符:
<style lang="scss" scoped> .a { /deep/ .b { /* ... */ } } </style>
結束語
深度作用選擇器實際上違反了 scoped 屬性的意義,且過多使用 scoped 會導致頁面打包文件體積增大。實際開發中我們應該盡量避免或少使用。可以采用加 class 名稱前綴的方式避免樣式污染,如:ivu-row-flex-middle。