前言
這篇文章開始我們就正式進入小程序的項目開發,這里主要功能包括:網絡請求,輪播圖,縱向列表,下拉刷新,上拉加載,item點擊傳值,頁面跳轉傳值.
效果圖
文件結構
配置
可以看到只有兩個頁面-index和info,所以在app.json中配置兩個頁面路徑(注意該文件不能有注釋)
{
"pages": [
"pages/index/index",
"pages/info/info"
],
"window": {
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#000",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "white"
}
}
列表頁面需要下拉刷新,所以在index.json中開啟下拉刷新,在info中關閉下拉刷新,同時設置title
//index.json
{
"navigationBarTitleText": "小程序",
"enablePullDownRefresh": true
}
//info.josn
{
"navigationBarTitleText": "詳情頁",
"enablePullDownRefresh": false
}
頁面
輪播圖
輪播圖由wx:for和<swiper-item>配合使用,wx:for="{{banners}}"
指定數據源數組,interval="1000"
指定自動切換的間隔,item為當前項的數據,index為下標,banners為js中的數據源,當js調用setdata并改變banners時,輪播圖會刷新
<swiper class="swiper" indicator-dots="true" autoplay="true" interval="3000">
<block wx:for="{{banners}}">
<swiper-item>
<image src="{{item.url}}" class="slide-image" mode="aspectFill" bindtap="itemClick" id="{{index}}" />
</swiper-item>
</block>
</swiper>
- swiper組件提供一些屬性,如自動切換,時間間隔,指示器等等
縱向列表
小程序不直接提供列表組件(如Android中的ListView,RecycleView),需要通過wx:for="{{listData}}
來重復渲染形成列表,原理同樣也是綁定數組,數組更新時刷新列表
<view class="list">
<block wx:for="{{listData}}">
<view class="list-item">
<image src=" {{item.url}} " class="item-image" mode="aspectFill" bindtap="itemClick" id=" {{index}}"/>
<view class="item-text">
<text class="item-title ">{{item.type}}</text>
<view class="item-msg ">
<text class="item-title ">{{item.who}}</text>
<text class="item-title ">{{item.desc}}</text>
</view>
</view>
</view>
</block>
</view>
- 列表同樣使用for來重復渲染,不同的是不需要
<swiper-item>
來包裹 - 可以使用
wx:key="_id"
來指定item的唯一性,如果不指定,微信會拋一個警告,但不會影響程序運行,具體wx:key的原理可查看官方文檔 - 建議動態列表指定wx:key,這樣效率會比較高,并且不會丟失item中的狀態
數據
輪播圖需要一個數組,列表需要一個數組,還需要記錄當前頁面,所以index的data部分:
Page({
data: {
banners: [],//輪播圖數據源,
pageNum: 1,//當前頁碼
listData: []//列表數據
}
)}
這里使用gank.io的api拉取數據用于輪播圖和列表,由于下拉和上拉都需要用到該請求,故提取為方法以便復用
,返回數據的格式:
{
"error": false,
"results": [
{
"_id": "587c6073421aa91194ca0e2c",
"createdAt": "2017-01-16T13:56:03.417Z",
"desc": "1-16",
"publishedAt": "2017-01-16T14:12:18.71Z",
"source": "chrome",
"type": "福利",
"url": "http://ww3.sinaimg.cn/large/610dc034gw1fbsfgssfrwj20u011h48y.jpg",
"used": true,
"who": "daimajia"
},
{
"_id": "5878471d421aa9119735ac13",
"createdAt": "2017-01-13T11:18:53.183Z",
"desc": "1-13",
"publishedAt": "2017-01-13T11:58:16.991Z",
"source": "chrome",
"type": "福利",
"url": "http://ww3.sinaimg.cn/large/610dc034gw1fbou2xsqpaj20u00u0q4h.jpg",
"used": true,
"who": "daimajia"
}
]
}
index.js數據處理
//獲取應用實例
var app = getApp()
Page({
data: {
banners: [],//輪播圖數據源,
pageNum: 1,//當前頁碼
listData: []//列表數據
},
requestData() {
var that = this
wx.request({
url: 'http://gank.io/api/data/福利/10/1',
success: function (res) {//更新數據刷新UI
banners: res.data.results,
listData: res.data.results
},
fail: function () {
},
complete: function () {
}
})
},
onLoad: function () {
this.requestData();
}
})
下拉刷新和底部自動加載
ok,經過上面的一些步驟,我的小程序已經可以順利運行并展示動態數據了,但是列表一般會配套刷新和分頁加載,在小程序中這兩個操作同樣也是有提供的:
-
onPullDownRefresh
為下拉的處理函數, -
wx.stopPullDownRefresh()
可以在請求完成后關閉拉下刷新, -
onReachBottom
為滑動到底部的處理函數,可用來做上拉加載分頁
在index.json中配置開啟了下拉刷新后,在index.js中處理對應事件:
Page({
onReachBottom: function () {//底部自動加載
this.data.pageNum++;
this.requestData();
},
onPullDownRefresh: function () {//下拉刷新
this.data.pageNum = 1;
this.requestData();
}
- 加載過程是耗時的,故需要給用戶一些loading
- 另外現在輪播和列表使用的是同一個請求,但是輪播實際永遠只需要展示第一頁的數據(圖片)就可以了,所以也需要做下數據處理,
- 網絡請求出錯應該給用戶對應的提示
綜合以上,則index.js(即邏輯層)最后的代碼如下:
//index.js
//獲取應用實例
var app = getApp()
Page({
onReachBottom: function () {
this.data.pageNum++;
this.requestData();
},
onPullDownRefresh: function () {
this.data.pageNum = 1;
this.requestData();
},
data: {
banners: [],//輪播圖數據源,
pageNum: 1,//當前頁碼
listData: []//列表數據
},
requestData() {
var that = this
console.log("當前頁碼" + this.data.pageNum)
if (that.data.listData.length < 1) {//第一次進來展示加載框
wx.showToast({
title: '加載中',
icon: 'loading',
duration: 500
})
} else {
wx.showNavigationBarLoading()
}
wx.request({
url: 'http://gank.io/api/data/福利/10/' + this.data.pageNum,
success: function (res) {
console.log("請求成功" + res)
wx.stopPullDownRefresh()//停止下拉刷新動畫
if (that.data.pageNum == 1) {
that.data.listData = []//清空數組
}
var list = that.data.listData;
for (var i = 0; i < res.data.results.length; i++) {
list.push(res.data.results[i]);
}
that.setData({
listData: list,//更新數據
banners: that.data.listData.slice(0,Math.min(9, that.data.listData.length))//截取數組
})
// success
},
fail: function () {
wx.showModal({
title: '加載出錯',
showCancel: false
})
},
complete: function () {//加載完成
wx.hideToast()
wx.hideNavigationBarLoading()
}
})
},
onLoad: function () {
this.requestData();
}
})
- 輪播和列表數據分開使用兩個數組存儲,其中輪播為列表的第一頁數據
- 由于
success
內部環境為wx.request
,故this相當于wx.request這個對象(js中,函數也是對象),對于Android開發者這一點是非常好理解的(相當于Android中的內部類),故需要在外面使用臨時變量存儲var that = this
,這樣使用that則是指向page - 用到一些js的數據操作:
that.data.listData = []//清空數組
;list.push(res.data.results[i]);//數組添加數據
;that.data.listData.slice(0,Math.min(9, that.data.listData.length))//截取數組
;
點擊跳轉
點擊輪播圖或者列表中的item需要到對應的詳情頁,展示該項的詳情信息,分為兩個步驟:
列表點擊傳值
即處理itemClick,并且需要獲取到該項的數據(banners[index]),所以在點擊事件中需要附帶當前的下標-index;
小程序提供兩種事件中傳值的方式:
1.使用組件通用屬性傳值,如id(適用于少量數據)
//wxml
<swiper class="swiper" indicator-dots="true" autoplay="true" interval="3000">
<block wx:for="{{banners}}">
<swiper-item>
<image src="{{item.url}}" class="slide-image" mode="aspectFill" bindtap="itemClick" id="{{index}}" />
</swiper-item>
</block>
</swiper>
//js
itemClick: function (event) {
console.log(event)
var index = event.target.id
},
2.使用事件中的dataset字段(適用于數據比較多)
//wxml
<swiper class="swiper" indicator-dots="true" autoplay="true" interval="3000">
<block wx:for="{{banners}}">
<swiper-item>
<image src="{{item.url}}" class="slide-image" mode="aspectFill" bindtap="itemClick" data-index="{{index}}" />
</swiper-item>
</block>
</swiper>
//js
itemClick: function (event) {
console.log(event)
var index = event.target.dataset.index
},
- dataset中的key使用data-keyName固定格式指定,并且大寫會被轉為小寫,在取值的時候則使用轉化后的駝峰命名形式的key(很奇葩,不得不吐槽一下)
跳轉傳值
ok,item的點擊事件和下標處理完成,接下來就是跳轉詳情頁了,那么小程序中跳轉應該怎么附帶參數呢,在詳情頁又該怎么取值呢?還是看代碼:
itemClick: function (event) {
console.log(event)
var index = event.target.id//取事件中附帶的index值
var item = this.data.listData[index]
wx.navigateTo({//跳轉
url: '../info/info?title=' + item.desc + "&imageUrl=" + item.url + "&resType=" + item.type + "&source=" + item.who
})
},
首先,從動點擊事件的參數中取到index,從而從數組中取到item數據,最后使用wx.navigateTo
跳轉頁面,該api需要指定跳轉頁面的路徑,參數以key=value形式拼接在路徑中(對于Android開發者是比較好理解的,這種形式與get請求參數拼接一致)
取值也非常簡單,只需要在詳情頁的onLoad方法中取參數里的值即可,
//info.js
Page({
data: {
title: '',
imageUrl: '',
resType: '',
source: ''
},
onLoad: function (res) {//取值
wx.setNavigationBarTitle({//動態設置當行欄標題
title: res.title
})
this.setData({//取值并更新數據和UI
title: res.title,
imageUrl: res.imageUrl,
resType: res.resType,
source: res.source,
})
}
})
- 頁面的參數傳遞全部需要key=value拼接的形式,在Android中是可以直接傳遞序列化對象的,但是小程序中好像并沒有提供傳遞對象的方式;
- 并且所有的參數都必須是String類型,其他類型內部均會自動轉為String傳遞,這一點也需要注意一下
ok,所有Demo中涉及到的內容基本都提到了,沒有什么特別難的點,有些地方開發思路需要做一下轉變,注意一下細節(小程序比較封閉,代碼書寫方式也很嚴格).下一篇會是進階的內容,包括Tab頁面,視頻播放
才疏學淺,還請大家及時指出博客中的問題,不慎感激.源碼github