微信小程序 組件模板和樣式

2022-04-25 11:43 更新

組件模板和樣式

類似于頁面,自定義組件擁有自己的 wxml 模板和 wxss 樣式。

組件模板

組件模板的寫法與頁面模板相同。組件模板與組件數(shù)據(jù)結(jié)合后生成的節(jié)點樹,將被插入到組件的引用位置上。

在組件模板中可以提供一個 <slot> 節(jié)點,用于承載組件引用時提供的子節(jié)點。

代碼示例:

<!-- 組件模板 -->
<view class="wrapper">
  <view>這里是組件的內(nèi)部節(jié)點</view>
  <slot></slot>
</view>
<!-- 引用組件的頁面模板 -->
<view>
  <component-tag-name>
    <!-- 這部分內(nèi)容將被放置在組件 <slot> 的位置上 -->
    <view>這里是插入到組件slot中的內(nèi)容</view>
  </component-tag-name>
</view>

注意,在模板中引用到的自定義組件及其對應(yīng)的節(jié)點名需要在 json 文件中顯式定義,否則會被當(dāng)作一個無意義的節(jié)點。除此以外,節(jié)點名也可以被聲明為抽象節(jié)點。

模板數(shù)據(jù)綁定

與普通的 WXML 模板類似,可以使用數(shù)據(jù)綁定,這樣就可以向子組件的屬性傳遞動態(tài)數(shù)據(jù)。

代碼示例:

<!-- 引用組件的頁面模板 -->
<view>
  <component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
    <!-- 這部分內(nèi)容將被放置在組件 <slot> 的位置上 -->
    <view>這里是插入到組件slot中的內(nèi)容</view>
  </component-tag-name>
</view>

在以上例子中,組件的屬性 propA 和 propB 將收到頁面?zhèn)鬟f的數(shù)據(jù)。頁面可以通過 setData 來改變綁定的數(shù)據(jù)字段。

注意:這樣的數(shù)據(jù)綁定只能傳遞 JSON 兼容數(shù)據(jù)。自基礎(chǔ)庫版本 2.0.9 開始,還可以在數(shù)據(jù)中包含函數(shù)(但這些函數(shù)不能在 WXML 中直接調(diào)用,只能傳遞給子組件)。

組件 wxml 的 slot

在組件的 wxml 中可以包含 slot 節(jié)點,用于承載組件使用者提供的 wxml 結(jié)構(gòu)。

默認(rèn)情況下,一個組件的 wxml 中只能有一個 slot 。需要使用多 slot 時,可以在組件 js 中聲明啟用。

Component({
  options: {
    multipleSlots: true // 在組件定義時的選項中啟用多slot支持
  },
  properties: { /* ... */ },
  methods: { /* ... */ }
})

此時,可以在這個組件的 wxml 中使用多個 slot ,以不同的 name 來區(qū)分。

<!-- 組件模板 -->
<view class="wrapper">
  <slot name="before"></slot>
  <view>這里是組件的內(nèi)部細(xì)節(jié)</view>
  <slot name="after"></slot>
</view>

使用時,用 slot 屬性來將節(jié)點插入到不同的 slot 上。

<!-- 引用組件的頁面模板 -->
<view>
  <component-tag-name>
    <!-- 這部分內(nèi)容將被放置在組件 <slot name="before"> 的位置上 -->
    <view slot="before">這里是插入到組件slot name="before"中的內(nèi)容</view>
    <!-- 這部分內(nèi)容將被放置在組件 <slot name="after"> 的位置上 -->
    <view slot="after">這里是插入到組件slot name="after"中的內(nèi)容</view>
  </component-tag-name>
</view>

組件樣式

組件對應(yīng) wxss 文件的樣式,只對組件wxml內(nèi)的節(jié)點生效。編寫組件樣式時,需要注意以下幾點:

  • 組件和引用組件的頁面不能使用id選擇器(#a)、屬性選擇器([a])和標(biāo)簽名選擇器,請改用class選擇器。
  • 組件和引用組件的頁面中使用后代選擇器(.a .b)在一些極端情況下會有非預(yù)期的表現(xiàn),如遇,請避免使用。
  • 子元素選擇器(.a>.b)只能用于 view 組件與其子節(jié)點之間,用于其他組件可能導(dǎo)致非預(yù)期的情況。
  • 繼承樣式,如 font 、 color ,會從組件外繼承到組件內(nèi)。
  • 除繼承樣式外, app.wxss 中的樣式、組件所在頁面的的樣式對自定義組件無效(除非更改組件樣式隔離選項)。
#a { } /* 在組件中不能使用 */
[a] { } /* 在組件中不能使用 */
button { } /* 在組件中不能使用 */
.a > .b { } /* 除非 .a 是 view 組件節(jié)點,否則不一定會生效 */

除此以外,組件可以指定它所在節(jié)點的默認(rèn)樣式,使用 :host 選擇器(需要包含基礎(chǔ)庫 1.7.2 或更高版本的開發(fā)者工具支持)。

代碼示例:

/* 組件 custom-component.wxss */
:host {
  color: yellow;
}
<!-- 頁面的 WXML -->
<custom-component>這段文本是黃色的</custom-component>

組件樣式隔離

默認(rèn)情況下,自定義組件的樣式只受到自定義組件 wxss 的影響。除非以下兩種情況:

  • app.wxss 或頁面的 wxss 中使用了標(biāo)簽名選擇器(或一些其他特殊選擇器)來直接指定樣式,這些選擇器會影響到頁面和全部組件。通常情況下這是不推薦的做法。
  • 指定特殊的樣式隔離選項 styleIsolation 。
Component({
  options: {
    styleIsolation: 'isolated'
  }
})

styleIsolation 選項從基礎(chǔ)庫版本 2.6.5 開始支持。它支持以下取值:

  • isolated 表示啟用樣式隔離,在自定義組件內(nèi)外,使用 class 指定的樣式將不會相互影響(一般情況下的默認(rèn)值);
  • apply-shared 表示頁面 wxss 樣式將影響到自定義組件,但自定義組件 wxss 中指定的樣式不會影響頁面;
  • shared 表示頁面 wxss 樣式將影響到自定義組件,自定義組件 wxss 中指定的樣式也會影響頁面和其他設(shè)置了 apply-shared 或 shared 的自定義組件。(這個選項在插件中不可用。)

使用后兩者時,請務(wù)必注意組件間樣式的相互影響。

如果這個 Component 構(gòu)造器用于構(gòu)造頁面 ,則默認(rèn)值為 shared ,且還有以下幾個額外的樣式隔離選項可用:

  • page-isolated 表示在這個頁面禁用 app.wxss ,同時,頁面的 wxss 不會影響到其他自定義組件;
  • page-apply-shared 表示在這個頁面禁用 app.wxss ,同時,頁面 wxss 樣式不會影響到其他自定義組件,但設(shè)為 shared 的自定義組件會影響到頁面;
  • page-shared 表示在這個頁面禁用 app.wxss ,同時,頁面 wxss 樣式會影響到其他設(shè)為 apply-shared 或 shared 的自定義組件,也會受到設(shè)為 shared 的自定義組件的影響。

從小程序基礎(chǔ)庫版本 2.10.1 開始,也可以在頁面或自定義組件的 json 文件中配置 styleIsolation (這樣就不需在 js 文件的 options 中再配置)。例如:

{
  "styleIsolation": "isolated"
}

此外,小程序基礎(chǔ)庫版本 2.2.3 以上支持 addGlobalClass 選項,即在 Component 的 options 中設(shè)置 addGlobalClass: true 。 這個選項等價于設(shè)置 styleIsolation: apply-shared ,但設(shè)置了 styleIsolation 選項后這個選項會失效。

代碼示例:

/* 組件 custom-component.js */
Component({
  options: {
    addGlobalClass: true,
  }
})
<!-- 組件 custom-component.wxml -->
<text class="red-text">這段文本的顏色由 `app.wxss` 和頁面 `wxss` 中的樣式定義來決定</text>
/* app.wxss */
.red-text {
  color: red;
}

外部樣式類

基礎(chǔ)庫 1.9.90 開始支持,低版本需做兼容處理。

有時,組件希望接受外部傳入的樣式類。此時可以在 Component 中用 externalClasses 定義段定義若干個外部樣式類。

這個特性可以用于實現(xiàn)類似于 view 組件的 hover-class 屬性:頁面可以提供一個樣式類,賦予 view 的 hover-class ,這個樣式類本身寫在頁面中而非 view 組件的實現(xiàn)中。

注意:在同一個節(jié)點上使用普通樣式類和外部樣式類時,兩個類的優(yōu)先級是未定義的,因此最好避免這種情況。

代碼示例:

/* 組件 custom-component.js */
Component({
  externalClasses: ['my-class']
})
<!-- 組件 custom-component.wxml -->
<custom-component class="my-class">這段文本的顏色由組件外的 class 決定</custom-component>

這樣,組件的使用者可以指定這個樣式類對應(yīng)的 class ,就像使用普通屬性一樣。在 2.7.1 之后,可以指定多個對應(yīng)的 class 。

代碼示例:

<!-- 頁面的 WXML -->
<custom-component my-class="red-text" />
<custom-component my-class="large-text" />
<!-- 以下寫法需要基礎(chǔ)庫版本 2.7.1 以上 -->
<custom-component my-class="red-text large-text" />
.red-text {
  color: red;
}
.large-text {
  font-size: 1.5em;
}

引用頁面或父組件的樣式

基礎(chǔ)庫 2.9.2 開始支持,低版本需做兼容處理

即使啟用了樣式隔離 isolated ,組件仍然可以在局部引用組件所在頁面的樣式或父組件的樣式。

例如,如果在頁面 wxss 中定義了:

.blue-text {
  color: blue;
}

在這個組件中可以使用 ~ 來引用這個類的樣式:

<view class="~blue-text"> 這段文本是藍色的 </view>

如果在一個組件的父組件 wxss 中定義了:

.red-text {
  color: red;
}

在這個組件中可以使用 ^ 來引用這個類的樣式:

<view class="^red-text"> 這段文本是紅色的 </view>

也可以連續(xù)使用多個 ^ 來引用祖先組件中的樣式。

注意:如果組件是比較獨立、通用的組件,請優(yōu)先使用外部樣式類的方式,而非直接引用父組件或頁面的樣式。

虛擬化組件節(jié)點

基礎(chǔ)庫 2.11.2 開始支持,低版本需做兼容處理

默認(rèn)情況下,自定義組件本身的那個節(jié)點是一個“普通”的節(jié)點,使用時可以在這個節(jié)點上設(shè)置 class style 、動畫、 flex 布局等,就如同普通的 view 組件節(jié)點一樣。

<!-- 頁面的 WXML -->
<view style="display: flex">
  <!-- 默認(rèn)情況下,這是一個普通的節(jié)點 -->
  <custom-component style="color: blue; flex: 1">藍色、滿寬的</custom-component>
</view>

但有些時候,自定義組件并不希望這個節(jié)點本身可以設(shè)置樣式、響應(yīng) flex 布局等,而是希望自定義組件內(nèi)部的第一層節(jié)點能夠響應(yīng) flex 布局或者樣式由自定義組件本身完全決定。

這種情況下,可以將這個自定義組件設(shè)置為“虛擬的”:

Component({
  options: {
    virtualHost: true
  },
  properties: {
    style: { // 定義 style 屬性可以拿到 style 屬性上設(shè)置的值
      type: String,
    }
  },
  externalClass: ['class'], // 可以將 class 設(shè)為 externalClass
})

這樣,可以將 flex 放入自定義組件內(nèi):

<!-- 頁面的 WXML -->
<view style="display: flex">
  <!-- 如果設(shè)置了 virtualHost ,節(jié)點上的樣式將失效 -->
  <custom-component style="color: blue">不是藍色的</custom-component>
</view>
<!-- custom-component.wxml -->
<view style="flex: 1">
  滿寬的
  <slot></slot>
</view>

需要注意的是,自定義組件節(jié)點上的 class style 和動畫將不再生效,但仍可以:

  • 將 style 定義成 properties 屬性來獲取 style 上設(shè)置的值;
  • 將 class 定義成 externalClasses 外部樣式類使得自定義組件 wxml 可以使用 class 值。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號