最近在開發一個基於Vue的后台管理系統,其中使用了element-ui第三方ui組件庫。使用過組件庫的人都知道,第三方組件往往會有一些默認的樣式,而有些又是我們想要改變的。
一、基礎(了解 <style></style> 的 scoped 屬性)
在編寫Vue代碼過程中,為了不讓父組件相同樣選擇器名稱設置的樣式影響到子組件,我們往往會給 <style></style> 標簽設置 scoped 屬性。但是如果設置了scoped屬性,在該組件內的 Css 就只能作用於當前組件中的元素。
實際上,它是通過使用 PostCSS 來實現以下轉換:
<template> <div class="example">hi</div> </template> <style scoped> .example { color: red; } </style>
轉換為:
<template> <div class="example" data-v-f3f3eg9>hi</div> </template> <style> .example[data-v-f3f3eg9] { color: red; } </style>
當然,我們也可以混合地使用本地樣式和全局樣式:
<style> /* 全局樣式 */ </style> <style scoped> /* 本地樣式 */ </style>
關於子組件根元素的樣式結果,還需要單獨敘述一下:
使用 scoped
后,父組件的樣式將不會滲透到子組件中。不過一個子組件的根節點會同時受其父組件的 scoped CSS 和子組件的 scoped CSS 的影響。這樣設計是為了讓父組件可以從布局的角度出發,調整其子組件根元素的樣式。
二、問題(使用第三方組件庫時修改默認樣式)
接下來,就介紹和解決一下,使用第三方組件庫時遇到的問題——無法修改默認樣式。
在項目中使用 element-ui 組件庫,設置樣式時發現根本無法覆蓋掉默認樣式,開始我也以為是選擇器的權重問題,后來發現,無論怎么加類名,樣式都無法生效。現在提供如下的解決方案:
使用深度作用選擇器:如果你希望 scoped
樣式中的一個選擇器能夠作用得“更深”,例如影響子組件,你可以使用 >>>
操作符:
<style scoped> .a >>> .b { /* 需要設置給子組件b的樣式 */ color: red; } </style>
上述代碼將會編譯成:
.a[data-v-f3f3eg9] .b { /* 需要設置給子組件b的樣式 */ color: red; }
但是,有些像 Sass 之類的預處理器無法正確解析 >>>
。這種情況下你可以使用 /deep/
或 ::v-deep
操作符取而代之——兩者都是 >>>
的別名,同樣可以正常工作。
<style scoped> .a /deep/ .b { /* 需要設置給子組件b的樣式 */ color: red; } </style>
如果使用了上面的 /deep/ 后發現樣式依然沒有生效,那么就給它再來個最高權重( !important ):
<style scoped> .a /deep/ .b { /* 需要設置給子組件b的樣式 */ color: red !important; } </style>