|
做過(guò) android 的都知道在 android 里面實(shí)現(xiàn) Tab切換 非常簡(jiǎn)單,使用 android 提供的 TabLayout+ViewPager 很容器就實(shí)現(xiàn)了 Tab切換 的效果。 但是小程序中是沒(méi)有提供類(lèi)似可以直接使用的組件,因此想要實(shí)現(xiàn)此功能需要我們自己去編碼實(shí)現(xiàn)。在上一篇文章中我提到的小程序練手項(xiàng)目就實(shí)現(xiàn)了 Tab切換 效果,具體效果圖可以參考文章微信小程序入門(mén)項(xiàng)目。 實(shí)現(xiàn)思路翻看小程序的文檔可以發(fā)現(xiàn),微信為我們提供了一個(gè) swiper 組件,通過(guò)該組件可以實(shí)現(xiàn) view 的滑動(dòng)切換,它的功能與 android 中的 ViewPager 是類(lèi)似的。因此實(shí)現(xiàn) Tab切換 現(xiàn)在只需要實(shí)現(xiàn)頭部的 Tabbar 即可,對(duì)于該功能我們可以采用多個(gè)橫向排列的 view 組件構(gòu)成一個(gè) Tabbar ,每個(gè) view 組件作為一個(gè) Tab 項(xiàng),然后再將其點(diǎn)擊事件與 swiper 進(jìn)行關(guān)聯(lián)即可實(shí)現(xiàn) Tab的點(diǎn)擊和滑動(dòng)切換功能。而對(duì)于 Tabbar 的當(dāng)前 Tab 項(xiàng)下面的指示器我們可以采用 border-bottom 樣式實(shí)現(xiàn),也可以單獨(dú)使用一個(gè) view 組件作為指示器,我這里采用的是第二種方式實(shí)現(xiàn)指示器。 代碼實(shí)現(xiàn)代碼如下: 頁(yè)面布局代碼
<viewclass="page">
<viewclass="navbar">
<blockwx:for="{{tabs}}"wx:key="*this">
<viewid="{{index}}"class="navbar__item {{activeIndex == index ? 'navbar__item_on' : ''}}"bindtap="navTabClick">
<viewclass="navbar__title">{{item.name}}</view>
</view>
</block>
<viewclass="navbar__slider"style="width: {{sliderWidth}}px; transform: translateX({{sliderOffset}}px); -webkit-transform: translateX({{sliderOffset}}px);"></view>
</view>
<viewstyle="position: absolute;top: 68rpx;width: 100%;height:{{contentHeight}}px">
<swipercurrent="{{activeIndex}}"duration="300"bindchange="bindChange">
<swiper-item>
<view>熱門(mén)視頻</view>
</swiper-item>
<swiper-item>
<view>比賽集錦</view>
</swiper-item>
<swiper-item>
<view>你懂專(zhuān)欄</view>
</swiper-item>
<swiper-item>
<view>天下足球</view>
</swiper-item>
</swiper>
</view>
</view>
布局樣式代碼
view , page {
padding: 0px;
margin: 0px;
}
.page {
height: 100%;
}
.navbar {
display: flex;
position: absolute;
z-index: 500;
top: 0;
width: 100%;
}
.navbar__item {
position: relative;
display: block;
flex: 1;
padding: 10rpx 0;
text-align: center;
font-size: 0;
height: 48rpx;
line-height: 48rpx;
<!-- NavBar的總高度為:height + padding-top + padding-bottom = 68rpx -->
}
.navbar__item_on {
color: #16B13A;
}
.navbar__slider {
position: absolute;
display: block;
content: " ";
left: 0;
bottom: 0;
height: 3px;
background-color: #16B13A;
transition: transform .3s;
}
.navbar__title{
display: inline-block;
font-size: 15px;
max-width: 8em;
text-align: center;
}
swiper {
height: 100%;
}
swiper-item{
width: 100%;
padding-top: 20rpx;
text-align: center;
}
js代碼
var tabs = [
{
name: "熱門(mén)視頻"
},
{
name: "比賽集錦"
},
{
name: "你懂專(zhuān)欄"
},
{
name: "天下足球"
}
];
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
tabs: tabs, //展示的數(shù)據(jù)
slideOffset: 0,//指示器每次移動(dòng)的距離
activeIndex: 0,//當(dāng)前展示的Tab項(xiàng)索引
sliderWidth: 96,//指示器的寬度,計(jì)算得到
contentHeight: 0//頁(yè)面除去頭部Tabbar后,內(nèi)容區(qū)的總高度,計(jì)算得到
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面加載
*/
onLoad: function(options){
var that = this;
wx.getSystemInfo({
success: function(res){
that.setData({
//計(jì)算相關(guān)寬度
sliderWidth: res.windowWidth / that.data.tabs.length,
sliderOffset: res.windowWidth / that.data.tabs.length * that.data.activeIndex,
contentHeight: res.windowHeight - res.windowWidth / 750 * 68//計(jì)算內(nèi)容區(qū)高度,rpx -> px計(jì)算
});
}
});
},
bindChange: function(e){
var current = e.detail.current;
this.setData({
activeIndex: current,
sliderOffset: this.data.sliderWidth * current
});
console.log("bindChange:" + current);
},
navTabClick: function(e){
this.setData({
sliderOffset: e.currentTarget.offsetLeft,
activeIndex: e.currentTarget.id
});
console.log("navTabClick:" + e.currentTarget.id);
}
})
總結(jié)上面的布局代碼和js代碼其實(shí)寫(xiě)起來(lái)都不難,關(guān)鍵在于css樣式的編寫(xiě),對(duì)于不熟悉CSS的人來(lái)說(shuō)調(diào)樣式太痛苦了。這個(gè)效果也是我調(diào)了好半天,參考了好多代碼之后寫(xiě)出來(lái)的,真o(╯□╰)o,看來(lái)想寫(xiě)好小程序還得好好學(xué)學(xué)CSS樣式。 |