類似vue或者react中的自定義組件
- ?程序允許我們使??定義組件的?式來(lái)構(gòu)建??。
1. 創(chuàng)建?定義組件
類似于頁(yè)面,一個(gè)自定義組件由
wxssjsonwxmljs4個(gè)文件組成
- 可以在微信開(kāi)發(fā)者?具中快速創(chuàng)建組件的?件結(jié)構(gòu),首先創(chuàng)建一個(gè)
component文件夾用于存放自定義組件。

使用微信開(kāi)發(fā)者工具快速創(chuàng)建組件目錄結(jié)構(gòu)

創(chuàng)建完成之后的文件結(jié)構(gòu)
2. 聲明組件
- ?先需要在組件的
json?件中進(jìn)??定義組件聲明;
{
"component": true,
"usingComponents": { // 可以使用其他組件}
}
-
新建一個(gè)頁(yè)面使用自定義組件 ;
自定義新的頁(yè)面 在新建的頁(yè)面的
json中使用自定義組件 :
{
"usingComponents": {
"Tabs": "../../component/Tabs/Tabs"
}
}
- 在
wxml文件中使用引入的自定義組件:
<Tabs>
</Tabs>
3. 自定義組件-Tabs樣式優(yōu)化
-
wxml代碼:
<!--
1. 自定義組件 - 優(yōu)化組件樣式
-->
<view class="tabs">
<view class="title">
<view wx:for="{{tabs}}" wx:key="{{item.id}}" class="title-item {{item.isActive ? 'active':''}}">
{{item.name}}
</view>
</view>
<view class="content">內(nèi)容</view>
</view>
- 需要將
tabs菜單的數(shù)據(jù)進(jìn)行抽取到數(shù)組中進(jìn)行遍歷展示:
// component/Tabs/Tabs.js
Component({
/**
* 組件的屬性列表
*/
properties: {
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
tabs: [{
id: 0,
name: '首頁(yè)',
isActive: true
},
{
id: 1,
name: '原創(chuàng)',
isActive: false
},
{
id: 2,
name: '分類',
isActive: false
},
{
id: 3,
name: '關(guān)于',
isActive: false
},
]
},
/**
* 組件的方法列表
*/
methods: {
}
})
- 編寫(xiě)樣式文件 :
.title {
display: flex;
padding: 10rpx 0;
}
.title-item {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.active {
color: red;
border-bottom: 5rpx solid #f00;
}
4. 實(shí)現(xiàn)tabs激活選中
- 需要為
view綁定一個(gè)單擊事件,并傳遞當(dāng)前點(diǎn)擊的item的索引 。
<!--
1. 自定義組件 - 優(yōu)化組件樣式
-->
<view class="tabs">
<view class="title">
<view
wx:for="{{tabs}}"
wx:key="{{item.id}}"
class="title-item {{item.isActive ? 'active':''}}"
bindtap="handleItemTap"
data-index="{{index}}">
{{item.name}}
</view>
</view>
<view class="content">內(nèi)容</view>
</view>

綁定一個(gè)點(diǎn)擊事件,并傳遞當(dāng)前點(diǎn)擊的 item項(xiàng)的索引
- 處理單擊事件:
/**
* 組件的方法列表
*/
methods: {
handleItemTap(e) {
// 進(jìn)行解構(gòu)賦值 下面這句相當(dāng)于 this.index = e.currentTarget.dataset.index
const { index } = e.currentTarget.dataset;
// 解構(gòu)是對(duì)復(fù)雜類型進(jìn)行解構(gòu)的時(shí)候復(fù)制一份變量引用而已
// 最嚴(yán)謹(jǐn)?shù)淖龇ň褪侵匦驴截愐环輸?shù)組再對(duì)這個(gè)數(shù)組的備份進(jìn)行處理
// 不要直接this.data.屬性
let { tabs } = this.data;
// 下面是最嚴(yán)謹(jǐn)?shù)膶?xiě)法
// let tabs = JSON.parse(JSON.stringify(this.data.tabs));
tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false);
this.setData({
tabs
})
}
}

需要在methods內(nèi)完成方法的編寫(xiě)
- 注意單擊事件中的解構(gòu)賦值:
// 進(jìn)行解構(gòu)賦值 下面這句相當(dāng)于 this.index = e.currentTarget.dataset.index
const { index } = e.currentTarget.dataset;
// 解構(gòu)是對(duì)復(fù)雜類型進(jìn)行解構(gòu)的時(shí)候復(fù)制一份變量引用而已
// 最嚴(yán)謹(jǐn)?shù)淖龇ň褪侵匦驴截愐环輸?shù)組再對(duì)這個(gè)數(shù)組的備份進(jìn)行處理
// 不要直接this.data.屬性
let { tabs } = this.data;
// 下面是最嚴(yán)謹(jǐn)?shù)膶?xiě)法
// let tabs = JSON.parse(JSON.stringify(this.data.tabs));
5. 父組件向子組件傳遞數(shù)據(jù)
- 在父組件引用子組件的
page中的標(biāo)簽上傳遞一個(gè)數(shù)據(jù): 里面的屬性名稱任意,符合命名規(guī)范
<Tabs parent="父親"></Tabs>
- 在子組件的
properties中接收父組件傳遞的值:

接收父組件傳遞的值
此時(shí)便可以在子組件的標(biāo)簽中直接使用該屬性。
將上面的
tabs數(shù)組通過(guò)父?jìng)髯拥姆绞剑瑥母附M件將數(shù)據(jù)傳遞到子組件:

在data域中定義一個(gè)tabs數(shù)組

父組件傳遞tabs數(shù)組

子組件接收父組件數(shù)據(jù)
- 但是以上的寫(xiě)法是有問(wèn)題的 : 因?yàn)樽咏M件中修改了
tabs的數(shù)據(jù),但是父組件中的數(shù)據(jù)并未實(shí)現(xiàn)修改:

父組件中的tabs未實(shí)現(xiàn)修改
- 實(shí)現(xiàn)父組件中數(shù)據(jù)的修改需要使用到子組件向父組件傳遞數(shù)據(jù)的方式。
6. 子組件向父組件傳遞數(shù)據(jù)
- 在父組件中定義一個(gè)父組件的自定義事件 :
bindItemChange

父組件自定義事件(我使用bindItemChange這種方式好像不被支持)

查閱官方文檔之后采用 bind:自定義事件名稱的方式可以
- 子組件向父組件通過(guò)事件的方式傳遞數(shù)據(jù) :
methods: {
handleItemTap(e) {
// 進(jìn)行解構(gòu)賦值 下面這句相當(dāng)于 this.index = e.currentTarget.dataset.index
const { index } = e.currentTarget.dataset;
// 點(diǎn)擊tabs觸發(fā)事件的時(shí)候需要傳遞數(shù)據(jù)給父組件 this.triggerEvent("父組件自定義事件的名稱",要傳遞的參數(shù))
// 子組件通過(guò)事件的方式向父組件傳遞數(shù)據(jù) 參數(shù)需要傳遞一個(gè)對(duì)象
this.triggerEvent("itemChange", { index });
}
}
- 父組件接收子組件通過(guò)事件傳遞的數(shù)據(jù) :
handleItemChange(e) {
// 解構(gòu)
const { index } = e.detail;
let { tabs } = this.data;
tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false)
this.setData({
// 這里 tabs 等價(jià)于 this.tabs = tabs
tabs
})
}
7. slot 插槽(占位符)標(biāo)簽
- 在自定義組件中使用
slot標(biāo)簽進(jìn)行占位 :

在自定義組件中使用slot進(jìn)行占位
- 在父組件中定義需要顯示的內(nèi)容 :

根據(jù)isActive屬性判斷顯示內(nèi)容
8. 組件的其他屬性
| 定義段 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
properties |
ObjectMap |
否 | 組件的對(duì)外屬性,是屬性名到屬性設(shè)置的映射表,參?下? |
data |
Object |
否 | 組件的內(nèi)部數(shù)據(jù),和 properties?同?于組件的模板渲染 |
observers |
Object |
否 | 組件數(shù)據(jù)字段監(jiān)聽(tīng)器,?于監(jiān)聽(tīng) properties 和data 的變化,參?數(shù)據(jù)監(jiān)聽(tīng)器 |
methods |
Object |
否 | 組件的?法,包括事件響應(yīng)函數(shù)和任意的?定義?法,關(guān)于事件響應(yīng)函數(shù)的使?,參?組件事件 |
created |
Function |
否 | 組件?命周期函數(shù),在組件實(shí)例剛剛被創(chuàng)建時(shí)執(zhí)?,注意此時(shí)不能調(diào)? setDatasetData ,參?組件?命周期 |
attached |
Function |
否 | 組件?命周期函數(shù),在組件實(shí)例進(jìn)???節(jié)點(diǎn)樹(shù)時(shí)執(zhí)?,參?組件?命周期 |
ready |
Function |
否 | 組件?命周期函數(shù),在組件布局完成后執(zhí)?,參?組件?命周期 |
moved |
Function |
否 | 組件?命周期函數(shù),在組件實(shí)例被移動(dòng)到節(jié)點(diǎn)樹(shù)另?個(gè)位置時(shí)執(zhí)?,參?組件?命周期 |
detached |
Function |
否 | 組件?命周期函數(shù),在組件實(shí)例被從??節(jié)點(diǎn)樹(shù)移除時(shí)執(zhí)?,參?組件?命周期 |
