|
小程序最近是越來(lái)越火了…… 做小程序有一段時(shí)間了,總結(jié)一下項(xiàng)目中遇到的問(wèn)題及解決辦法吧。 項(xiàng)目中有個(gè)多 tab 嵌套的需求,進(jìn)入程序主界面下面有兩個(gè) tab,進(jìn)入A模塊后,A模塊最底下又有多個(gè)tab,每個(gè)tab上又嵌了2-4個(gè)不等的tab。。。 這種變態(tài)需求只能自定義tab了。 其實(shí)如果項(xiàng)目不是很復(fù)雜,沒(méi)有多tab嵌套的需求,完全可以用小程序官方的 tabBar,方便快捷。
一、Demo結(jié)構(gòu)先看效果圖吧 結(jié)構(gòu)是這樣的:程序主界面包含兩個(gè) tab:主頁(yè)和我的,主頁(yè)又包含兩個(gè)tab:最熱和最新;我的也包含兩個(gè)tab:電影和音樂(lè)。 關(guān)系圖如下:
項(xiàng)目
主頁(yè)
最熱
最新
我的
電影
音樂(lè)
二、開(kāi)始擼代碼再看代碼結(jié)構(gòu)
兩種頁(yè)面結(jié)構(gòu)小程序的頁(yè)面分為兩種: page 和 components 。 page 就是普通的頁(yè)面, components 是小程序?yàn)閷?shí)現(xiàn)模塊化而提供的自定義組件。 相同點(diǎn): 都由四個(gè)文件: .js 、 .json 、 .wxml 、 .wxss 、構(gòu)成, .wxml 、 .wxss 寫(xiě)法完全相同。 不同點(diǎn):
{
"component": true,
"usingComponents": {
"movie": "movie/movie",
"music": "music/music"
}
}
page 的 js 代碼
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面加載
*/
onLoad: function (options) {
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面顯示
*/
onShow: function () {
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面隱藏
*/
onHide: function () {
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面卸載
*/
onUnload: function () {
},
/**
* 頁(yè)面相關(guān)事件處理函數(shù)--監(jiān)聽(tīng)用戶下拉動(dòng)作
*/
onPullDownRefresh: function () {
},
/**
* 頁(yè)面上拉觸底事件的處理函數(shù)
*/
onReachBottom: function () {
},
/**
* 用戶點(diǎn)擊右上角分享
*/
onShareAppMessage: function () {
}
})
component 的 js 代碼
Component({
/**
* 組件的屬性列表
*/
properties: {
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
},
/**
* 組件的方法列表
*/
methods: {
}
})
本例中每個(gè) tab 都是一個(gè)小程序中定義的 component , 只有最外層包裹的 myapp 是 page ,因?yàn)?nbsp;page 中只能嵌入 component , component 中也可以嵌入 component 。 代碼解析先看 myapp ,這是程序的主界面。它包含了兩個(gè) tab : home 和 mine ,分別對(duì)應(yīng)頁(yè)面下方的 主頁(yè) 和 我的 。 要引入自定義組件需要在 myapp.json 文件中聲明:
{
"usingComponents":{
"home": "./home/home",
"mine": "./mine/mine"
}
}
現(xiàn)在,就可以在 myapp.wxml 文件中愉快的引用了
<view class='container'>
<view class='content'>
<view wx:if='{{currentTab == 0}}'>
<home/>
</view>
<view wx:if='{{currentTab == 1}}'>
<mine/>
</view>
</view>
<!-- 下面的兩個(gè)tab -->
<view class='bottom-tab'>
<view class='tab-item {{currentTab == 0 ? "active" : ""}}' data-current="0" bindtap='switchTab'>
<image src='{{currentTab == 0 ? "../../assets/home_active.png" : "../../assets/home.png"}}' class='item-img'></image>
<text class='item-text'>主頁(yè)</text>
</view>
<view class='tab-item {{currentTab == 1 ? "active" : ""}}' data-current="1" bindtap='switchTab'>
<image src='{{currentTab == 1 ? "../../assets/mine_active.png" : "../../assets/mine.png"}}' class='item-img'></image>
<text class='item-text'>我的</text>
</view>
</view>
</view>
tab切換的原理是根據(jù) wx:if 或者 hidden 來(lái)控制視圖的顯示和隱藏,頁(yè)面的 data 中設(shè)置一個(gè)變量 currentTab 來(lái)記錄當(dāng)前點(diǎn)擊的是哪個(gè)tab,每次點(diǎn)擊的時(shí)候更新 currentTab 的值。 切換tab的方法:
switchTab(e) {
this.setData({ currentTab: e.currentTarget.dataset.current });
}
這里有幾個(gè)需要注意的點(diǎn):
再看主頁(yè) home ,它本身是一個(gè) component ,又包含了兩個(gè) component :最熱 hot 和 最新 new 。 同樣需要在 home.json 中注冊(cè)這兩個(gè)組件
{
"component": true,
"usingComponents": {
"hot": "hot/hot",
"new": "new/new"
}
}
注意 home 本身是一個(gè) component ,所以需要注明 "component": true 布局文件 home.wxml
<view class='container'>
<view class='tab-wrapper'>
<view id='tableft' class='tab-left {{currentTab === 0 ? "tab-active":""}}' bindtap='switchTab'>最熱</view>
<view id='tabright' class='tab-right {{currentTab === 1 ? "tab-active" : ""}}' bindtap='switchTab'>最新</view>
</view>
<view class='content-wrapper' wx:if='{{currentTab === 0}}'><hot/></view>
<view class='content-wrapper' wx:if='{{currentTab === 1}}'><new/></view>
</view>
js文件 home.js
Component({
/**
* 組件的屬性列表
*/
properties: {
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
currentTab: 0
},
/**
* 組件的方法列表
*/
methods: {
switchTab(e) {
console.log(e)
let tab = e.currentTarget.id
if (tab === 'tableft') {
this.setData({ currentTab: 0 })
} else if (tab === 'tabright') {
this.setData({ currentTab: 1 })
}
}
}
})
給兩個(gè) tab 的 view 設(shè)置了 id 屬性值為 tableft 和 tabright ,設(shè)置了id后就可以用 e.currentTarget.id 獲取到當(dāng)前點(diǎn)擊的是哪個(gè)元素了。 其他幾個(gè)頁(yè)面的代碼都大同小異,主要是判斷當(dāng)前點(diǎn)擊的是哪個(gè) tab ,然后根據(jù) currentTab判斷該顯示或隱藏哪個(gè)組件。 |