與頁面(Page
)相似,組件也由json
膘融、wxml
腊凶、wxss
划咐、js
四個(gè)文件組成。
與頁面不同的是钧萍,需要在組件對(duì)應(yīng)的json
文件中作出如下聲明:
{
"component": true
}
以表示當(dāng)前創(chuàng)建的是一個(gè)自定義組件褐缠。目前通過微信小程序開發(fā)者工具創(chuàng)建組件時(shí),json
文件中會(huì)自動(dòng)生成這個(gè)定義风瘦,無需手動(dòng)處理队魏。
組件的簡(jiǎn)單定義
組件中wxml
和wxss
文件的編寫與普通頁面沒有不同。需要注意的是可以在wxss
文件中使用:host
選擇器來指定組件的默認(rèn)樣式万搔。
代碼示例如下:
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
</view>
/* components/component-user.wxss */
/* 此處使用:host選擇器來指定組件的默認(rèn)樣式 */
:host {
color: blue;
font-style: italic;
}
組件的使用
如果需要在某個(gè)頁面中引用組件胡桨,則需要在這個(gè)頁面對(duì)應(yīng)的json
文件中對(duì)需要使用的組件進(jìn)行聲明。此處以index
頁面為例:
在index.json
文件中聲明要引用的組件:
{
"usingComponents": {
"user": "/components/component-user"
}
}
user
是為組件聲明的別名瞬雹,作為在index.wxml
中引用組件的標(biāo)簽名昧谊。
在index.wxml
中引用組件:
<!-- index.wxml -->
<view>
<text>index.wxml</text>
<user />
</view>
效果如下:組件模板
插入單個(gè)節(jié)點(diǎn)
如果要在自定義組件中特定位置插入一個(gè)節(jié)點(diǎn),則此時(shí)需要使用組件模板酗捌。
模板定義如下:
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
<!-- 使用slot標(biāo)簽作為插入view的節(jié)點(diǎn) -->
<slot />
</view>
在index.wxml
中引用如下:
<!-- index.wxml -->
<view class="container">
<text>index.wxml</text>
<user>
<!-- 這個(gè)view節(jié)點(diǎn)會(huì)插入到slot標(biāo)簽處作為自定義組件的一個(gè)節(jié)點(diǎn) -->
<view style="color:#F78AE0">這個(gè)view會(huì)被插入到自定義組件的slot標(biāo)簽處</view>
</user>
</view>
效果如下:
注意:可以在同一個(gè)
slot
標(biāo)簽處插入多個(gè)節(jié)點(diǎn)呢诬。
向特定位置插入節(jié)點(diǎn)
自定義組件默認(rèn)僅支持向slot
處插入節(jié)點(diǎn)。如果想在一個(gè)自定義組件的特定位置插入節(jié)點(diǎn)的話胖缤,首先需要在js
文件開啟支持多個(gè)slot
的聲明尚镰。
// components/component-user.js
Component({
options: {
// 支持多個(gè)slot
multipleSlots: true
}
})
并且在wxml
文件中為slot
命名:
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
<!-- 使用slot標(biāo)簽作為插入view的節(jié)點(diǎn) -->
<slot name="another-slot" />
<view style='width:100%;height:1px;background:black' />
<slot name="slot" />
</view>
然后在index.wxml
中使用通過指定slot的名字來指定插入的位置:
<!-- index.wxml -->
<view class="container">
<text>index.wxml</text>
<user>
<!-- 這個(gè)view節(jié)點(diǎn)會(huì)插入到slot標(biāo)簽處作為自定義組件的一個(gè)節(jié)點(diǎn) -->
<view style="color:#F78AE0" slot="slot">這個(gè)view會(huì)被插入到slot處</view>
<view style="color:#6638F0" slot="another-slot">這個(gè)view會(huì)被插入到another-slot處</view>
</user>
</view>
效果如下:
注意:在開啟了多slot支持后,如果在組件中存在沒有命名的slot哪廓,并且index.wxml中也有未指定插入位置的節(jié)點(diǎn)狗唉,則默認(rèn)插入無名稱的slot處。
事件綁定
在使用模板時(shí)撩独,如果要為綁定的節(jié)點(diǎn)綁定事件敞曹,則添加在模板內(nèi)和引用處都可以,具體可以根據(jù)業(yè)務(wù)需求來區(qū)分综膀。
比如引用自定義組件的多處業(yè)務(wù)邏輯完全相同澳迫,則可以將事件綁定在模板中,減少重復(fù)代碼剧劝。如果引用自定義組件處業(yè)務(wù)有所不同橄登,則可以在引用處進(jìn)行事件綁定。
在模板中綁定事件時(shí),wxml
文件中代碼與普通頁面中的代碼相同拢锹,區(qū)別在于js
文件中方法的定義:
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
<!-- 使用slot標(biāo)簽作為插入view的節(jié)點(diǎn) -->
<slot name="another-slot" />
<view style='width:100%;height:1px;background:black' />
<slot name="slot" catchtap="onSlotClick" />
</view>
// components/component-user.js
Component({
options: {
// 支持多個(gè)slot
multipleSlots: true
},
/**
* 組件的方法列表
*/
methods: {
onSlotClick: function(event) {
console.log("onSlotClick in component-user.js")
}
}
})
在組件模板中綁定事件時(shí)谣妻,需要將事件的監(jiān)聽方法定義在methods
中。
事件的冒泡順序
在使用事件模板時(shí)其實(shí)可以在模板wxml
文件和頁面wxml
文件中都對(duì)同一個(gè)節(jié)點(diǎn)進(jìn)行綁定卒稳,此時(shí)事件的冒泡順序可能會(huì)讓一部分人感到困擾蹋半。
在index
頁面中綁定事件代碼如下:
<!-- index.wxml -->
<view class="container">
<text>index.wxml</text>
<user>
<!-- 這個(gè)view節(jié)點(diǎn)會(huì)插入到slot標(biāo)簽處作為自定義組件的一個(gè)節(jié)點(diǎn) -->
<view style="color:#F78AE0" slot="slot" bindtap="onSlotClick">這個(gè)view會(huì)被插入到slot處</view>
<view style="color:#6638F0" slot="another-slot">這個(gè)view會(huì)被插入到another-slot處</view>
</user>
</view>
Page({
onSlotClick: function(event) {
console.log("onSlotClick in index.js")
}
})
此時(shí)點(diǎn)擊slot,輸出如下:
有的同學(xué)會(huì)認(rèn)為
component-user
中的事件先響應(yīng)而index
中的事件后充坑。其實(shí)這是種錯(cuò)誤的認(rèn)知减江。這些同學(xué)錯(cuò)誤的將
index.wxml
中的節(jié)點(diǎn)當(dāng)做了component-user.wxml
的外層節(jié)點(diǎn),而實(shí)際上index.wxml
中定義的節(jié)點(diǎn)是要插入到component.user.wxml
中的捻爷,實(shí)際為component-user.wxml
中的子節(jié)點(diǎn)辈灼。
綁定數(shù)據(jù)
為自定義組件綁定數(shù)據(jù)和為模板綁定數(shù)據(jù)差別不大。區(qū)別在于為模板綁定數(shù)據(jù)時(shí)需要使用屬性data-<data-set-name>
也榄,而為自定義組件綁定數(shù)據(jù)需要預(yù)先定義要綁定數(shù)據(jù)的屬性巡莹。
首先在component-user.js
中定義要綁定事件的屬性:
// components/component-user.js
Component({
options: {
// 支持多個(gè)slot
multipleSlots: true
},
/**
* 組件的屬性列表
*/
properties: {
// 用于接收傳入的數(shù)據(jù)
user: Object
},
/**
* 組件的方法列表
*/
methods: {
onSlotClick: function(event) {
console.log("onSlotClick in component-user.js")
}
}
})
在component-user.js
根據(jù)定義的屬性綁定數(shù)據(jù):
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
<!-- 使用slot標(biāo)簽作為插入view的節(jié)點(diǎn) -->
<slot name="another-slot" />
<view style='width:100%;height:1px;background:black' />
<slot name="slot" catchtap="onSlotClick" />
<view>name:{{user.name}}</view>
<view>age:{{user.age}}</view>
<view>gender:{{user.gender}}</view>
</view>
然后在引用組件的時(shí)候就可以使用user
屬性來為組件傳遞數(shù)據(jù):
<!-- index.wxml -->
<view class="container">
<text>index.wxml</text>
<!-- 使用user屬性來向組件傳遞數(shù)據(jù) -->
<user user="{{user}}">
<!-- 這個(gè)view節(jié)點(diǎn)會(huì)插入到slot標(biāo)簽處作為自定義組件的一個(gè)節(jié)點(diǎn) -->
<view style="color:#F78AE0" slot="slot" bindtap="onSlotClick">這個(gè)view會(huì)被插入到slot處</view>
<view style="color:#6638F0" slot="another-slot">這個(gè)view會(huì)被插入到another-slot處</view>
</user>
</view>
Page({
onReady: function() {
this.setData({
user: {
name: "自定義組件示例",
age: "0",
gender: "undetermined"
}
})
},
onSlotClick: function(event) {
console.log("onSlotClick in component-user.js")
}
})
顯示效果如下:behaviors
behaviors
用于在不同組件間進(jìn)行代碼共享。類似于Java中多個(gè)不同的類實(shí)現(xiàn)了相同的接口甜紫,則都具備了該接口的特性降宅。示例如下:
定義一個(gè)behavior
:
// component-behavior.js
module.exports = Behavior({
properties: {
userInBehavior: Object
},
methods: {
onSlotClick: function(event) {
console.log("onSlotClick called in component-behavior.js")
}
},
lifetimes: {
created() {
console.log("created called in component-behavior.js")
},
attached() {
console.log("attached called in component-behavior.js")
},
detached() {
console.log("detached called in component-behavior.js")
},
ready() {
console.log("ready called in component-behavior.js")
}
},
})
我們?cè)?code>component-behavior.js中定義了屬性userInBehavior
、onSlotClick
方法棵介,并且添加了生命周期的回調(diào)钉鸯。
在component-user.js
也添加生命周期回調(diào),并且引入behavior
:
// components/component-user.js
var mBehavoir = require('component-behavior.js')
Component({
options: {
// 支持多個(gè)slot
multipleSlots: true
},
// 此處引入定義的behavior
behaviors: [mBehavoir],
/**
* 組件的屬性列表
*/
properties: {
// 用于接收傳入的數(shù)據(jù)
user: Object
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
},
/**
* 組件的方法列表
*/
methods: {
// 此處監(jiān)聽方法的定義與behavior中相同邮辽,behavior中的同名方法會(huì)被覆蓋
onSlotClick: function(event) {
console.log("onSlotClick in component-user.js")
}
},
lifetimes: {
created() {
console.log("created called in component-user.js")
},
attached() {
console.log("attached called in component-user.js")
},
detached() {
console.log("detached called in component-user.js")
},
ready() {
console.log("ready called in component-user.js")
}
}
})
component-user.wxml
修改如下:
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
<!-- 使用slot標(biāo)簽作為插入view的節(jié)點(diǎn) -->
<slot name="another-slot" />
<view style='width:100%;height:1px;background:black' />
<slot name="slot" catchtap="onSlotClick" />
<view>name:{{user.name}}</view>
<view>age:{{user.age}}</view>
<view>gender:{{user.gender}}</view>
</view>
至此唠雕,behavior
的定義和引入完成。運(yùn)行程序吨述,控制臺(tái)輸出如下:
我們發(fā)現(xiàn)
component-behavior.js
和component-user.js
中的生命周期回調(diào)方法被依次調(diào)用岩睁。在執(zhí)行點(diǎn)擊操作,結(jié)果如下:
我們發(fā)現(xiàn)
component-behavior.js
中的事件監(jiān)聽方法沒有執(zhí)行揣云。將
component-user.js
中的事件監(jiān)聽方法注釋掉再重試:這次
component-behavior.js
中的事件監(jiān)聽方法被調(diào)用了捕儒。總結(jié)一下:
在
behavior
中定義的生命周期回調(diào)與組件模板中定義的生命周期回調(diào)不會(huì)互相覆蓋,而普通方法(例如事件監(jiān)聽方法為組件模板中的方法覆蓋behavior
中的方法)邓夕。
我們還在component-behavior.js
中定義了一個(gè)新的屬性userInBehavior
刘莹,嘗試在index
中傳遞數(shù)據(jù):
Page({
onReady: function() {
this.setData({
user: {
name: "自定義組件示例",
age: "0",
gender: "undetermined"
},
userInBehavior: {
name: "name in behavior"
}
})
},
onSlotClick: function(event) {
console.log("onSlotClick in index.js")
}
})
在index.wxml
中綁定數(shù)據(jù):
<!-- index.wxml -->
<view class="container">
<text>index.wxml</text>
<!-- 使用user屬性來向組件傳遞數(shù)據(jù) -->
<user user="{{user}}" userInBehavior="{{userInBehavior}}">
<!-- 這個(gè)view節(jié)點(diǎn)會(huì)插入到slot標(biāo)簽處作為自定義組件的一個(gè)節(jié)點(diǎn) -->
<view style="color:#F78AE0" slot="slot" bindtap="onSlotClick">這個(gè)view會(huì)被插入到slot處</view>
<view style="color:#6638F0" slot="another-slot">這個(gè)view會(huì)被插入到another-slot處</view>
<view style="color:red">這個(gè)節(jié)點(diǎn)使用了behavior中的數(shù)據(jù):name={{userInBehavior.name}}</view>
</user>
</view>
為了讓未指定插入位置的節(jié)點(diǎn)能夠正常顯示,還需要在component-user.wxml
中添加一個(gè)未命名的slot
標(biāo)簽:
<!--components/component-user.wxml-->
<view>
<text>這是自定義組件User</text>
<!-- 使用slot標(biāo)簽作為插入view的節(jié)點(diǎn) -->
<slot name="another-slot" />
<view style='width:100%;height:1px;background:black' />
<slot name="slot" catchtap="onSlotClick" />
<view>name:{{user.name}}</view>
<view>age:{{user.age}}</view>
<view>gender:{{user.gender}}</view>
<slot />
</view>
效果如下:
此處僅介紹了小程序自定義組件的簡(jiǎn)單使用焚刚,如果需要了解更復(fù)雜的特性点弯,請(qǐng)?jiān)L問官方文檔-自定義組件。