1. 問題
使用 Taro 開發微信小程序的時候,將原來的main.js
頁面拆分爲多個函數式組件的時候,發現main.js
已經引入的scss
文件裏面的類,在自定義組件中不生效
2. 解決:
自定義組件對應的樣式文件,只對該組件內的節點生效。編寫組件樣式時,需要注意以下幾點:
- 組件和引用組件的頁面不能使用
id 選擇器(#a)
、屬性選擇器([a])
和標籤名選擇器
,請改用class 選擇器
。 - 組件和引用組件的頁面中使用
後代選擇器(.a .b)
在一些極端情況下會有非預期的表現,如遇,請避免使用。 - 子元素選擇器
(.a > .b)
只能用於 View 組件與其子節點之間,用於其他組件可能導致非預期的情況。 -
繼承樣式
,如font
、 `color ,會從組件外(父組件)繼承到組件內。但是引用組件時在組件節點上書寫的 className 無效。 (具體解決方案請參見下面的外部和全局樣式介紹。) - 除繼承樣式外,
app.scss
中的樣式、引入組件所在頁面的樣式,均對自定義組件無效。
#a { } /* 在組件中不能使用 */
[a] { } /* 在組件中不能使用 */
button { } /* 在組件中不能使用 */
.a > .b { } /* 除非 .a 是 view 組件節點,否則不一定會生效 */
真香,原來是第2點的原因,本人使用了後代選擇器,父類
是在原頁面
,而子類
是在自定義組件
中,所以子類樣式並不會生效。
3. 解決自定義組件樣式使用問題
3.1 自定義組件制定默認樣式
組件可以指定它所在節點的默認樣式,使用 :host
選擇器。只需要在樣式文件中輸入該選擇器,立即生效,非常好用,親測有效
/* 該自定義組件的默認樣式 */
:host {
color: red;
font-weight: bold;
font-size: 30PX;
}
3.2 externalClasses 定義若干個外部樣式類
MyPage.js
export default class MyPage extends Component {
render () {
return <CustomComp my-class="red-text" />
}
}
MyPage.scss
.red-text {
color: red;
}
CustomComp.js
export default class CustomComp extends Component {
static externalClasses = ['my-class']
render () {
return <View className="my-class">這段文本的顏色由組件外的 class 決定</View>
}
}
上面的 CustomComp 使用了ES6 extends來創建了組件,那麼問題來了,如果是函數式組件
,那該如何寫呢?哈哈很簡單
export default function CustomComp (props){
CustomComp.externalClasses = ['my-class']
render () {
return <View className="my-class">這段文本的顏色由組件外的 class 決定</View>
}
}
注意:externalClasses
需要使用短橫線命名法 (kebab-case)
,而不是 React 慣用的 駝峯命名法 (camelCase)。否則無效。
3.3 全局樣式類
使用外部樣式類可以讓組件使用制定的組件樣式類,如果希望組件外樣式類能夠完全影響組件內部嗎可以將組件構造器中的options.addGlobalClass
字段置爲 true
CustomComp.js
export default class CustomComp extends Component {
static options = {
addGlobalClass: true
}
render () {
return <View className="red-text">這段文本的顏色由組件外的 class 決定</View>
}
}
組件外的樣式定義
.red-text {
color: red;
}
如果使用函數式組件
...
CustomComp.options = { addGlobalClass: true }
...
總結
1.解決了自定義組件(引用頁面)樣式不生效的問題
2.可以使用:host
來寫默認樣式
3.可以選擇使用外部的特定樣式類或者全局樣式類,不同的組件寫法略微不同