1. 程式人生 > >微信小程式(七):仿找事吧APP附近三公里Demo

微信小程式(七):仿找事吧APP附近三公里Demo

功能點:輪播;列表,下拉重新整理上拉載入更多;地圖;網路請求;資料繫結等
文字仿照了 找事吧app 附近三公里功能,並感謝找事吧資料的提供。考慮到資料的私密性,本文貼出的程式碼並沒有貼出請求URL,敬請諒解。
本文基於微信小程式公測版,IDE:微信開發者工具 0.10.102800

效果圖如下:

enter image description here

分析一下頁面,主要內容分為頂部輪播,中間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
}