微信小程式(七):仿找事吧APP附近三公里Demo
功能點:輪播;列表,下拉重新整理上拉載入更多;地圖;網路請求;資料繫結等
文字仿照了 找事吧app 附近三公里功能,並感謝找事吧資料的提供。考慮到資料的私密性,本文貼出的程式碼並沒有貼出請求URL,敬請諒解。
本文基於微信小程式公測版,IDE:微信開發者工具 0.10.102800
效果圖如下:
分析一下頁面,主要內容分為頂部輪播,中間10個分類圖示的排版和單擊事件,下部列表下拉重新整理上拉載入更多。大部分知識點前面都講過。這裡主要說一下微信小程式中的資料繫結,前後臺傳值以及載入更多時的資料合併。
1. 資料繫結和前後臺傳值
中間分類圖示的佈局檔案:
<view class="items" wx:for="{{array}}" wx:for-item="item" bindtap="typeclick" data-code="{{item.code}}" data-text="{{item.text}}" >
<image class="item-img" mode="aspectFit" src="{{item.src}}"></image>
<view class="item-text">{{item.text}}</view>
</view>
可以看出是以 控制屬性 wx:for
array
來迴圈渲染布局,並對view綁定了單擊事件bindtap="typeclick"
。因為每一個分類點選都會重新整理下部列表,所以需要在事件中獲得當前分類資料的code。小程式中提供自定義標籤 data-XXX
,供開發者使用來繫結資料,XXX
可以隨意取名,這裡我們用 data-code="{{item.code}}" data-text="{{item.text}}"
把每條資料的code和text傳給function typeclick
。
然後在js中的 typeclick 函式中,我們可以通過event拿到繫結的資料。
// 分類item單擊事件
typeclick: function (e) {
total = 0;
code = e.currentTarget.dataset.code + "";
var name = e.currentTarget.dataset.text + "";
this.data.dataArray = [];
this.setData({
title: "附近三公里: " + name
})
this.periphery();
},
e.currentTarget.dataset.code
後邊的code就是我們在佈局檔案中定義的 data-XXX
中的XXX,這裡需要注意一下,因為js的機制,有時候我們拿到的資料型別可能不對,需要自己處理一下。
2. 載入更多時的資料合併
// 網路請求
periphery: function () {
var that = this
//sliderList
wx.request({
url: 'http://xxx',
method: 'POST',
data: {
city: "深圳",
code: code,
count: count + "",
total: total + "",
lat: app.globalData.latitude + "",
lng: app.globalData.longitude + ""
},
header: {
'Accept': 'application/json'
},
success: function (res) {
that.data.dataArray = that.data.dataArray.concat(res.data.data.list)
that.setData({
dataArray: that.data.dataArray
})
setTimeout(function () {
that.setData({
loadingHidden: true
})
}, 1000)
}
})
},
因為列表有上拉重新整理和下拉載入更多的功能。所以每次的網路請求通過 total和count控制每次請求的資料的頁碼,然後在 success 回撥中把資料拼接到原來的資料集合上。
首先注意一點。在wx.request的回撥中,我們不能直接用this.data.dataArray
來取data標籤下的dataArray,因為這裡的this代表的並不是js的全域性上下文物件,他對應的是這個function的上下文。所以我們需要在 wx.request 的外部,通過一個變數來儲存js的全域性上下文物件,var that = this
,然後在回撥中用 that.data.dataArray
然後說資料拼接,需要用到concat 關鍵字,他可以把其引數拼接到呼叫者身上。that.data.dataArray.concat(res.data.data.list)
這裡需要注意請求返回的資料格式,res.data
代表的是返回的json,然後自己根據資料格式拼接,直到取到資料集合。
其次因為上拉和下拉的性質不同,其處理方式也不同,下拉需要把資料集合置為空並從頭開始去資料。上拉需要處理total,來取下一個count條數的資料。程式碼如下:
// 下拉重新整理回撥介面
onPullDownRefresh: function () {
total = 0;
this.data.dataArray = [];
this.periphery();
wx.stopPullDownRefresh;
},
// 上拉載入回撥介面
onReachBottom: function () {
total += count;
this.periphery();
},
下面附上完整的程式碼:
<!--main.wxml-->
<view>
<swiper class="swiper_box" indicator-dots="{{indicatorDots}}" vertical="{{vertical}}"
autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" bindchange="swiperchange">
<block wx:for="{{images}}">
<swiper-item bindtap="itemclick" data-id="{{item.img}}" data-name="{{item.name}}">
<image src="{{item.img}}" class="slide-image"/>
</swiper-item>
</block>
</swiper>
</view>
<!--nearby.wxml-->
<scroll-view class="sv" scroll-y="true">
<view style="overflow:hidden;">
<view class="items" wx:for="{{array}}" wx:for-item="item" bindtap="typeclick" data-code="{{item.code}}" data-text="{{item.text}}" >
<image class="item-img" mode="aspectFit" src="{{item.src}}"></image>
<view class="item-text">{{item.text}}</view>
</view>
</view>
<view class="data">
<text class="data-title">{{title}}</text>
<view style="overflow:hidden;">
<view class="data-items" wx:for="{{dataArray}}" wx:for-item="item" wx:key="id" bindtap="openmap"
data-lat="{{item.lat}}" data-lng="{{item.lng}}" data-name="{{item.name}}" data-address="{{item.address}}">
<image class="data-item-img" mode="aspectFit" src="{{item.img}}"></image>
<view class="data-item-text">
<view style="width:100%; font-size: 30rpx; padding:2rpx;">{{item.name}}</view>
<view style="width:100%; font-size: 25rpx; padding:2rpx;">{{item.address}}</view>
<view style="width:100%; font-size: 25rpx; padding:2rpx;">{{item.phone}}</view>
</view>
</view>
</view>
</view>
</scroll-view>
<loading hidden="{{loadingHidden}}">
載入中...
</loading>
/**main.wxss**/
.swiper_box {
width: 100%;
}
swiper-item image {
width: 100%;
display: inline-block;
overflow: hidden;
}
.sv{
background-color:#efeff4;
margin-top: 10rpx
}
.items{
float:left;
width: 20%;
background-color:#fff;
}
.item-img{
width: 100%;
height: 60rpx;
}
.item-text{
width: 100%;
height: 60rpx;
font-size: 25rpx;
text-align:center;
}
.data{
margin-top: 10rpx;
background-color:#fff;
padding: 10rpx;
}
.data-title{
padding-left: 10rpx;
padding-top: 15rpx;
}
.data-items{
width: 100%;
margin-top: 10rpx;
margin-bottom: 10rpx;
overflow: hidden;
}
.data-item-img{
width: 20%;
height:120rpx;
float:left;
}
.data-item-text{
width: 75%;
padding: 5rpx;
height:120rpx;
float:left;
}
//main.js
//獲取應用例項
var app = getApp()
var count = 10;
var total = 0;
var code = "2";
Page({
data: {
title: "附近三公里",
indicatorDots: true,
vertical: false,
autoplay: true,
interval: 3000,
duration: 1000,
loadingHidden: false, // loading
array: [{
code: '1',
id: 'icon_1',
src: 'http://xxx',
text: '家政'
}, {
code: '2',
id: 'icon_2',
src: 'http://xxx',
text: '藥店'
}, {
code: '3',
id: 'icon_3',
src: 'http://xxx',
text: '銀行'
}, {
code: '4',
id: 'icon_4',
src: 'http://xxx',
text: '維修'
}, {
code: '5',
id: 'icon_5',
src: 'http://xxx',
text: '公廁'
}, {
code: '6',
id: 'icon_6',
src: 'http://xxx',
text: '醫院'
}, {
code: '7',
id: 'icon_7',
src: 'http://xxx',
text: '加油站'
}, {
code: '8',
id: 'icon_8',
src: 'http://xxx',
text: '汽車洗護'
}, {
code: '9',
id: 'icon_9',
src: 'http://xxx',
text: '營業廳'
}, {
code: '10',
id: 'icon_10',
src: 'http://xxx',
text: '停車場'
}],
dataArray: []
},
//事件處理函式
swiperchange: function (e) {
// 此處寫 輪播 改變時會觸發的 change 事件
},
// 輪播item點選事件
itemclick: function (e) {
wx.showToast({
title: e.currentTarget.dataset.id + "",
icon: 'success',
duration: 2000
})
},
// 分類item單擊事件
typeclick: function (e) {
total = 0;
code = e.currentTarget.dataset.code + "";
var name = e.currentTarget.dataset.text + "";
this.data.dataArray = [];
this.setData({
title: "附近三公里: " + name
})
this.periphery();
},
onLoad: function () {
console.log('onLoad')
var that = this
count = 10;
total = 0;
//sliderList
wx.request({
url: 'http://xxx',
method: 'POST',
data: {
type: "1"
},
header: {
'Accept': 'application/json'
},
success: function (res) {
that.setData({
images: res.data.data.guanggao
})
}
})
this.periphery();
},
// 網路請求
periphery: function () {
var that = this
//sliderList
wx.request({
url: 'http://xxx',
method: 'POST',
data: {
city: "深圳",
code: code,
count: count + "",
total: total + "",
lat: app.globalData.latitude + "",
lng: app.globalData.longitude + ""
},
header: {
'Accept': 'application/json'
},
success: function (res) {
that.data.dataArray = that.data.dataArray.concat(res.data.data.list)
that.setData({
dataArray: that.data.dataArray
})
setTimeout(function () {
that.setData({
loadingHidden: true
})
}, 1000)
}
})
},
// 下拉重新整理回撥介面
onPullDownRefresh: function () {
total = 0;
this.data.dataArray = [];
this.periphery();
wx.stopPullDownRefresh;
},
// 上拉載入回撥介面
onReachBottom: function () {
total += count;
this.periphery();
},
openmap: function (e) {
wx.openLocation({
latitude: e.currentTarget.dataset.lat , // 緯度,範圍為-90~90,負數表示南緯
longitude: e.currentTarget.dataset.lng, // 經度,範圍為-180~180,負數表示西經
scale: 28, // 縮放比例
name: e.currentTarget.dataset.name, // 位置名
address: e.currentTarget.dataset.address, // 地址的詳細說明
success: function(res){
// success
},
fail: function() {
// fail
},
complete: function() {
// complete
}
})
},
})
main.json
{
"enablePullDownRefresh": true
}