前言
NBA總決賽結束還沒一週,馬上世界盃就如期而至。大家在熬夜看球,而我關在小黑屋默默碼字(可憐臉)。在體驗到小程式的方便快捷省記憶體之後,前段時間的“騎勇大戰”果斷用了小程式觀看。由於體驗不錯,又正在學習小程式知識,馬上就想動手實踐學習一下“騰訊體育”小程式的製作。到目前為止,只想說一句“選擇是好的,過程是一言難盡的”,雖然還沒全部完成,但也遇到不少問題,希望此分享可以給你帶來幫助(原始碼)。
效果圖
(乾巴巴的開講,還不如先來波動圖)
問題及解決方案
1、scroll-view元件
讓我們先來看看開發文件
- scroll-x
在此專案中,首頁——世界盃的頭部是一個橫向滑動的scroll-view
元件,在設定了scroll-x
屬性後,並未達到預期效果,scroll-view中的每個部分還是自成一行。在一番簡單搜尋後得出,設定white-space: nowrap;
樣式就可使其在同一行。
- scroll-y
NBA賽事詳情頁中有5個sroll-view,雖然內容有點少,但還是看得出有scroll的效果的。
同樣的,在製作豎向滾動效果時,需要設定sroll-y
屬性,在官方的文件中也特別說明了
使用豎向滾動時,需要給
scroll-view
一個固定高度,通過 WXSS 設定 height。
那麼問題來了,在scroll-view
並非佔滿全屏的情況下,如何確定其高度呢?
首先想到,把包含選項卡和scroll-view
的大盒子固定寬度後,在遵循文件流的情況下,將 scroll-view
高度設定為 100%不就好了嗎?但是,在如此一番設定之後,scroll-view
的高度變成了大盒子的高度???(黑人問號臉),最重要的是scroll-view
中的內容不能完全顯示,這就頭疼了。
隨後馬上想到可以使用彈性佈局,固定其選項卡的高度,下方的scroll-view
設定flex: 1
,這難道還解決不了嗎?是的,bug永相隨。下圖可以看到,選項卡的高度明顯變小,要是scroll-view的內容再多一點,選項卡就被擠到窒息了。
最後無奈只好將scroll-view的高度逐漸調整到螢幕底部的高度,簡直不要太粗暴,缺點是在不同螢幕尺寸裝置上檢視,效果不一。如果有大佬可提供較好解決方案,懇請指教。
2、swiper元件
開發文件是好朋友,讓我們再來看看。
swiper
元件在小程式中非常常見,它可在有限的區域展示更多內容,還能增加頁面的視覺動態效果,總之就是好。(但,好東西也是有槽點的啦)
1) 從上面動圖可看出,NBA賽事詳情頁中也使用到了swiper
元件,並且與頭部的導航進行了繫結,滑動swiper
可改變導航欄的狀態,點選導航欄選項可切換swiper-item
。這個實現較為簡單,步驟如下:
- 在
data
中新增一個表示下標的變數curIndex
; - 將此變數繫結到導航欄各個選項,同時使用一個三目運算子進行
wx:if
條件渲染,若curIndex
等於當前選項的下標,則在其底部新增一個偽元素表示選中; - 將
curIndex
繫結到swiper
的current
屬性中,通過選項卡的bindtap
事件和swiper
的bindchange
事件實時切換swiper-item
。
話不多說,貼上程式碼:
//nbaMatches.wxml
<view class="info_hd">
<view class="headerMenu {{curIndex===index?'on':''}}"
wx:for="{{nbaMenu}}"
data-index="{{index}}"
bindtap="switchSort">
<view class="nbaSort">{{item.nbaSort}}</view>
</view>
</view>
<view class="info_bd">
<swiper current="{{curIndex}}" bindchange="bindswiper">
...
</swiper>
</view>
複製程式碼
//nbaMatches.js
bindswiper(e) {
this.setData({
curIndex: e.detail.current
})
},
switchSort(e) {
console.log(e.currentTarget.dataset.index);
this.setData({
curIndex: e.currentTarget.dataset.index?e.currentTarget.dataset.index: 0
})
}
複製程式碼
2)此專案的“熱門”頁也使用了一個swiper
元件,相比普通swiper
的使用,這個更為複雜。此處的swiper
不再是與有限個的選項進行互動,而是與無限個的日期進行互動。難道一年365天就要365個swiper-item
? 嚇得老夫虎軀一震。
經過一場“豬腦子”風暴後,還是沒有想出完美的解決方案,只好設定有限個swiper-item
來初步實現所需效果。
還是貼程式碼吧!
//swiper的bindchange事件
changeMatch(e) {
const current = e.detail.current; //獲取當前位置
const befInd = this.data.swiperCurIndex; //獲取滑動前的位置
const index = current - befInd;
if (index <= -1) { //判斷左滑右滑
this.preDay(); //日期切換至前一天
} else if (index >= 1) {
this.nextDay(); //日期切換至後一天
} else {
return
}
}
複製程式碼
// nextDay() 方法類似
preDay() {
let day = this.data.day;
let month = this.data.month;
let week= this.data.week;
let i = this.data.i;
if (i<=0) { //週一至週日的迴圈切換
i = 6;
}else {
i--;
}
if(day<=1) { //日期本月第一天時,將日期切換至上月最後一天
month--;
day = this.data.daysCountArr[month-1];
}else {
day--; //否則切換至前一天
}
this.setData({
swiperCurIndex: this.data.swiperCurIndex-1,
month,
day,
i,
week: this.data.weekArr[i],
curDate: month+'月'+day+'日'+' '+this.data.weekArr[i]
})
}
複製程式碼
如果大佬們有解決方案歡迎交流討論。詳細程式碼檢視可點選這裡。
3、選項卡
天啦嚕!你連選項卡都要說?(笑哭)聽我解釋。
通常我們使用的選項卡中的選項都是 2 到 4 個,如果不嫌麻煩,我們只要將選項卡和其對應的內容逐個在.wxml
中寫出來就好了。但是,一旦選項變多,若逐個寫出,那.wxml
中的程式碼將跟“懶婆娘的裹腳布”似的。此時,使用wx:for
來迴圈輸出選項就非常有必要了。另外,如果每個選項中的內容都是類似的就更好了,可通過選項卡的點選事件獲得當前選項的id
,根據id
使用wx:if
條件渲染來決定當前選項卡顯示的資料。在這又要cue一下我們的NBA賽事詳情頁,此頁面中的球員榜這個swiper-item
就包含了一個有 5 個選項的選項卡。
詳細程式碼檢視可點選這裡。
4、自定義日曆
為了更好的體驗,體育賽事總要加入日曆,方便使用者檢視賽事安排。若使用picker
元件,使用者體驗可能差強人意,那麼如何自定義一個日曆呢?在參照了各路大神的方法後得出以下分析:
- 可左右切換月份並顯示當月日曆。騰訊體育官方小程式的日曆可左右滑動切換,與“熱門”頁類似。由於還沒有解決方案,在這裡沒有使用
swiper
元件。日曆主體中的每月日期是一個二維陣列,每月的週數則為陣列的length,因此wxml中的日期輸出需要使用兩重wx:for
。部分程式碼如下:
<view class="calendar_box" wx:for="{{dateList}}" wx:for-item="week" wx:key="{{index}}" style="{{index==0?'justify-content: flex-end;':''}}">
<view wx:for="{{week}}" data-date="{{item}}"
class="weekday_label {{item.value==selectedDate?'active_label':''}}" bindtap="selectDate">
<view class="date">
<text>{{item.date}}</text>
</view>
<view class="gameNumBox">
<text class="gameNum">{{item.gameNum}}</text>
<text>場比賽</text>
</view>
</view>
</view>
複製程式碼
- 預設高亮顯示當天日期,點選具體日期高亮顯示。這個實現起來較為簡單,只需得到通過點選事件獲取當前點選日期,在
.wxml
中使用三目運算子判斷獲取日期與資料中的日期是否相同,從而達到高亮顯示的效果。 - 返回今天。點選“返回今天”可回退至“熱門”頁並顯示當天的賽事。使用小程式自帶 API ——
wx.navigateBack(OBJECT)
即可返回上一頁面,以下為文件截圖: 值得注意的是:
wx.navigateTo 和 wx.redirectTo 不允許跳轉到 tabbar 頁面,只能用 wx.switchTab 跳轉到 tabbar 頁面
結語
由於是第一次寫專案,相關知識儲備也還不夠,從專案開始到現在,遇到的問題可不止這些,但解決問題的過程是辛苦也是富有樂趣的。目前這個專案也還有很多部分沒有實現,但會持續更新,如果感興趣歡迎交流討論。之後將全面學習mpvue和wepy小程式框架,若使用框架寫這個專案相信會簡單一些,有機會可以寫一個mpvue版。
我的專案在這裡哦。