在使用原生框架開發小程序時遇到一個問題,在 app.wxss
中定義的全局樣式在自定義組件中不生效。后來發現是由於小程序組件樣式隔離的配置導致的。
太長不看版
在組件的 json 文件中添加如下配置,全局樣式即可生效。
// component.json
"styleIsolation": "apply-shared"
如果偏好在 js 文件中進行配置,或版本號 < 2.10.1,也可以寫在 js 文件中,效果相同。
// component.js
Component({
options: {
styleIsolation: 'apply-shared'
}
})
如果版本號 < 2.6.5,可以使用如下配置代替 styleIsolation: 'apply-shared'
// component.js
Component({
options: {
addGlobalClass: true
}
})
組件樣式隔離
組件的 styleIsolation
有三個可選值:
isolated
:默認值,組件內外的樣式互不影響apply-shared
:接收外部(包括父頁面和全局)的樣式,但組件內的樣式不影響外部shared
:接收外部樣式,同時組件內的樣式會共享到頁面
demo 試驗
為了更直觀,寫了一個 demo 進行了簡單試驗。
定義一個組件comp
,並在頁面 index
中引入組件:
<!-- comp.wxml -->
<view class="test1 testbox">comp1</view>
<view class="test2 testbox">comp2</view>
<view class="test3 testbox">comp3</view>
<!-- index.wxml -->
<comp />
<view class="test3 testbox">index3</view>
然后在全局、頁面、組件中分別定義 test1, test2, test3 的顏色為紅、綠、藍色(省略了 testbox 的樣式):
/* app.wxss */
.test1 {
background-color: lightpink;
}
/* components/index.wxss */
.test2 {
background-color: lightgreen;
}
/* components/comp.wxss */
.test3 {
background-color: lightblue;
}
之后對組件的 styleIsolation 屬性進行不同取值,結果如下:
可以看到,默認模式 isolated下,父頁面和全局樣式都不生效;apply-shared 模式下,頁面和全局樣式能作用到組件中;shared 模式下組件樣式還會反過來作用到父頁面上。
優先級
另外,經過測試,對於相同的選擇器,樣式的優先級為 組件樣式 > 頁面樣式 > 全局樣式,對於組件來說這基本符合直覺。不過如果組件應用了 shared,那么其中樣式也會覆蓋頁面中的樣式,這就有點奇怪。
綜上,個人建議除非特殊需要,否則最好慎用 shared 模式,並且盡量減少選擇器沖突和相互覆蓋,以免造成不必要的靈異事故。對於需要共享的樣式,可以根據情況抽取到全局或采用引入 css 文件的方式實現。
頁面的隔離配置
由於小程序的頁面實際上也是組件,所以同樣可以設置 styleIsolation 屬性,並且與自定義組件不同的是頁面的默認取值為 share
,因此頁面中默認可以應用全局樣式。
另外,對於頁面還額外增加了三個屬性取值。雖然文檔中有各自的描述,但我經過試驗后感到十分迷惑,完全沒有搞懂各自的確切作用和區別;甚至還有頁面設置為 isolated / page-isolated 之后頁面自己的樣式都失效了這種神秘 bug,可能是實現上還存在問題。所以建議不要隨便更改頁面的 styleIsolation 配置,感興趣的可以點擊文末鏈接自行研究試驗。
只有一個還算比較確定的選項,配置 page-shared
之后,頁面(以及其中的組件)將屏蔽 app.wxss
中的全局樣式,並且其他方面的影響應該較小,如果有需要可以嘗試。