最近在開發一個基於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>
