微信小程序開發 初體驗:實現首頁輪播圖、圖標按鈕、列表下拉刷新上拉加載更多等功能

說點兒閒話

上週一,技術主管突然分給我一個任務,是微信頁面的開發任務,專門指明瞭讓用 iView Weapp來作。html

iView Weapp是一套高質量的微信小程序 UI 組件庫

意思很明顯了,是開發微信小程序呢,以前從沒作太小程序項目,不過好久以前本身學過一點兒,上手起來不難,這裏分享一下實現的過程。vue

最終效果 先睹爲快

微信小程序 效果圖.gif

安裝小程序開發者工具 並 新建一個小程序代碼

首先,須要安裝小程序開發者工具,若是已經裝過了,直接用就能夠了。json

按照微信開放文檔 你的第一個小程序 新建一個小程序,開發過程當中,小程序的 AppID能夠先試用測試號。
1.jpg小程序

vs code 編寫小程序代碼

在vs code中進行代碼編寫,vs code須要安裝如下插件:
1. minapp微信小程序

支持微信小程序標籤、屬性的智能補全,而且提示中包含文檔內容(同時支持原生小程序、mpvue 和 wepy 框架,並提供 snippets)。

2.wechat-snippetapi

這個插件主要的功能就是代碼輔助,代碼片斷自動完成,能夠做爲上個插件的補充。

3.wxml數組

這款插件用於將wxml代碼進行高亮顯示,而且提供代碼格式化的功能,可將代碼格式化爲較易閱讀的樣式。

4.vscode weapp api 緩存

爲 VSCode 提供微信小程序 API 提示及代碼片斷。

搭建項目

小程序目錄結構 這裏再也不贅述,看官方文檔就好。微信

小程序配置 按照文檔來配置小程序, 全局配置和頁面配置等。網絡

新建的小程序默認已經有index和logs,那麼,我這裏是將index,複製一份改成mine,新建list,刪除logs,list的數據將直接使用logs的數據作爲例子,因此,logs能夠先留着本身看看。
而後,作以下修改:
app.json
pages:

"pages": [  
    "pages/index/index",  
    "pages/list/list",  
    "pages/mine/mine"  
  ],

底部導航菜單

先在根目錄下新建images,將須要用的圖標放在images/tabBar/下,而後在app.json增長 tabBar:

"tabBar": {  
    "color": "#333333",  
    "selectedColor": "#2e75b6",  
    "list": [  
      {  
        "pagePath": "pages/index/index",  
        "selectedIconPath": "images/tabBar/tabBar-s1.png",  
        "iconPath": "images/tabBar/tabBar-s2.png",  
        "text": "首頁"  
      },  
      {  
        "pagePath": "pages/list/list",  
        "selectedIconPath": "images/tabBar/tabBar-k1.png",  
        "iconPath": "images/tabBar/tabBar-k2.png",  
        "text": "列表"  
      },  
      {  
        "pagePath": "pages/mine/mine",  
        "selectedIconPath": "images/tabBar/tabBar-w1.png",  
        "iconPath": "images/tabBar/tabBar-w2.png",  
        "text": "個人"  
      }  
    ]  
  },

效果如圖:
1.png
2.png
3.png

引入iView Weapp

快速上手 - iView Weapp按照文檔,到 GitHub 下載 iView Weapp 的代碼,將 dist 目錄拷貝到本身的項目中。而後按需引用組件。

首頁index頁面實現

輪播圖

首頁上方先放一個輪播圖,直接使用 組件中的視圖容器—— swiper 滑塊視圖容器 便可實現輪播圖,仍是先把圖片放置在images中,而後在index.js中配置data,並設置swiper的屬性。

index.js:

Page({  
  data: {  
    imgUrls: [  
      '../../images/index/pic1.jpg',  
      '../../images/index/pic2.png',  
      '../../images/index/pic3.jpg'  
    ],  
    indicatorDots: true,  // 是否顯示面板指示點
    autoplay: true,  // 是否自動切換
    interval: 2000,  // 自動切換時間間隔
    duration: 1000,   // 滑動動畫時長
  },  
})

在index.wxml中:

<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" class="swiper">  
  <block wx:for="{{imgUrls}}" wx:key="index">  
    <swiper-item>  
      <image src="{{item}}" class="slide-image" />  
    </swiper-item>  
  </block>  
</swiper>

index.wxss:

/**index.wxss**/  
  
.swiper {  
  height: 300rpx;  
  border-bottom: 1rpx solid #ccc;  
}  
  
.slide-image {  
  width: 100%;  
  height: 100%;  
}

圖標宮格、通告欄、信息卡片

圖標宮格、通告欄、信息卡片這三個模塊,直接使用 iView Weapp 的組件。
在index.json中:

{  
  "usingComponents": {  
    "i-grid": "../../dist/grid/index",  
    "i-grid-item": "../../dist/grid-item/index",  
    "i-grid-icon": "../../dist/grid-icon/index",  
    "i-grid-label": "../../dist/grid-label/index",  
    "i-icon": "../../dist/icon/index",  
    "i-row": "../../dist/row/index",  
    "i-card": "../../dist/card/index",  
    "i-panel": "../../dist/panel/index",  
    "i-notice-bar": "../../dist/notice-bar/index"  
  }  
}

在index.wxml中,swiper下繼續寫:

<i-grid>  
    <i-row>  
        <i-grid-item>  
            <i-grid-icon>  
                <i-icon size="24" type="activity" />  
                <i-grid-label>宮格</i-grid-label>  
            </i-grid-icon>  
        </i-grid-item>  
        <i-grid-item>  
            <i-grid-icon>  
                <i-icon size="24" type="addressbook" />  
                <i-grid-label>宮格</i-grid-label>  
            </i-grid-icon>  
        </i-grid-item>  
        <i-grid-item>  
            <i-grid-icon>  
                <i-icon size="24" type="barrage" />  
                <i-grid-label>宮格</i-grid-label>  
            </i-grid-icon>  
        </i-grid-item>  
    </i-row>  
    <i-row>  
        <i-grid-item>  
            <i-grid-icon>  
                <i-icon size="24" type="collection" />  
                <i-grid-label>宮格</i-grid-label>  
            </i-grid-icon>  
        </i-grid-item>  
        <i-grid-item>  
            <i-grid-icon>  
                <i-icon size="24" type="computer" />  
                <i-grid-label>宮格</i-grid-label>  
            </i-grid-icon>  
        </i-grid-item>  
        <i-grid-item>  
            <i-grid-icon>  
                <i-icon size="24" type="coupons" />  
                <i-grid-label>宮格</i-grid-label>  
            </i-grid-icon>  
        </i-grid-item>  
    </i-row>  
</i-grid>  
  
<i-panel title="滾動 通告欄">  
    <i-notice-bar icon="systemprompt" loop speed="800">  
        2018年世界盃,將於6月14日至7月15日舉行;2018年世界盃,將於6月14日至7月15日舉行;  
    </i-notice-bar>  
</i-panel>  
  
<view style="margin: 16px">標題</view>  
<i-card full title="卡片標題" extra="額外內容" thumb="![](file:///C:\Users\SSJ\AppData\Roaming\Tencent\QQTempSys\%W@GJ$ACOF(TYDYECOKVDYB.png)https://i.loli.net/2017/08/21/599a521472424.jpg">  
    <view slot="content">內容不錯</view>  
    <view slot="footer">尾部內容</view>  
</i-card>

首頁佈局就算是完成了,是否是還挺簡單的呢?跟着作下去,你將獲得一個簡單的微信小程序Demo。

個人mine頁面實現

獲取用戶信息:名字、頭像,及 功能列表,直接上代碼:
mine.js:

//mine.js
//獲取應用實例
const app = getApp()

Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },
  //事件處理函數
  bindViewTap: function() {
    // 點擊頭像跳轉
    wx.navigateTo({
      url: '../mine/mine'
    })
  },
  onLoad: function () {
    if (app.globalData.userInfo) {
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
    } else if (this.data.canIUse){
      // 因爲 getUserInfo 是網絡請求,可能會在 Page.onLoad 以後才返回
      // 因此此處加入 callback 以防止這種狀況
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 在沒有 open-type=getUserInfo 版本的兼容處理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        },
        fail: function () {
          //獲取用戶信息失敗後。請跳轉受權頁面
          wx.showModal({
            title: '警告',
            content: '還沒有進行受權,請點擊肯定跳轉到受權頁面進行受權。',
            success: function (res) {
              if (res.confirm) {
                console.log('用戶點擊肯定')
                wx.navigateTo({
                  url: '../tologin/tologin',
                })
              }
            }
          })
        }
      })
    }
  },
  getUserInfo: function(e) {
    // console.log(e)
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  }
})

mine.json:

{
  "navigationBarTitleText": "我的中心",
  "usingComponents": {
    "i-panel": "../../dist/panel/index",
    "i-cell-group": "../../dist/cell-group/index",
    "i-cell": "../../dist/cell/index"
  }
}

mine.wxml :

<!--mine.wxml-->
<view class="container">
  <view class="userinfo">
    <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 獲取頭像暱稱 </button>
    <block wx:else>
      <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
</view>

<i-panel title="功能">
    <i-cell-group>          
        <i-cell title="個人xx" is-link url="pages/mine/mine"></i-cell>  
        <i-cell title="xxxxxxx" is-link url="pages/mine/mine"></i-cell>  
        <i-cell title="xxxxxxx" is-link url="pages/mine/mine"></i-cell>  
        <i-cell title="消費記錄" is-link url="pages/mine/mine"></i-cell>  
    </i-cell-group>
</i-panel>

mine.wxss:

/**mine.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 20rpx 0;
  box-sizing: border-box;
} 

.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.userinfo-avatar {
  width: 128rpx;
  height: 128rpx;
  margin: 20rpx;
  border-radius: 50%;
}

.userinfo-nickname {
  color: #aaa;
}

.usermotto {
  margin: 20px;
}

列表list頁面實現

list.json:

{
  "navigationBarTitleText": "列表頁",
  "enablePullDownRefresh": true, // 下拉刷新
  "usingComponents": {
    "i-card": "../../dist/card/index",
    "i-spin": "../../dist/spin/index",
    "i-load-more": "../../dist/load-more/index"
  }
}

list實現

list.js:

//list.js
const util = require('../../utils/util.js')
Page({
  data: {
    logs: [],
  },
  onLoad: function() {
    this.clearCache(); //清本頁緩存
    this.getArticles(0); //第一次加載數據
  },
  getArticles: function(pageno) {
    this.setData({
      logs: (wx.getStorageSync('logs') || []).map(log => {
        return util.formatTime(new Date(log))
      })
    })
  },
})

list.wxml:

<!-- list.wxml -->
<view class="container data-list">
  <block wx:for="{{logs}}" wx:for-item="log" wx:key="index">
    <i-card full title="{{index + 1}}.卡片標題" extra="額外內容" thumb="https://i.loli.net/2017/08/21/599a521472424.jpg">
      <view slot="content">{{index + 1}}.內容不錯</view>
      <view slot="footer">{{log}}</view>
    </i-card>
  </block>
</view>

下拉刷新、上拉加載更多

實現原理:
一、下拉刷新:因爲小程序數據是實時渲染的。咱們把data{}內的數據清空從新加載便可實現下拉刷新。
二、上拉加載更多(頁面上拉觸底事件):新獲取的數據追加到data{}內的原數據便可。因爲小程序數據是實時渲染,小程序在保持原數據顯示不變的基礎上,自動追加渲染顯示新數據。

注意(小程序官方有說明):
一、上拉加載更多 不要用scroll-view,用普通的view便可。
二、下拉刷新須要在 當前頁面.json 裏配置

{
   "enablePullDownRefresh": true 
 }

page()屬性裏有兩個屬性是關於頁面下拉刷新 和 上拉加載更多的:

onPullDownRefresh Function 頁面相關事件處理函數–監聽用戶下拉動做
onReachBottom Function 頁面上拉觸底事件的處理函數

主要參考了以上思路。
實現代碼:
在list.wxml裏view的視圖容器內的底部增長:

<i-spin size="large" fix wx:if="{{ spinShow }}"></i-spin>
    <i-load-more tip="{{loadMoreTip}}" loading="{{ loadMore }}" />

list.js修改成以下:

//list.js
const util = require('../../utils/util.js')
var page = 0; //當前頁
var totalPages = 3; //總頁數
Page({
  data: {
    logs: [],
    //加載樣式是否顯示
    spinShow: true,
    loadMore: true,
    loadMoreTip: '加載中',
    allLoaded: false
  },
  onLoad: function() {
    this.clearCache(); //清本頁緩存
    this.getArticles(0); //第一次加載數據
  },
  getArticles: function(pageno) {
    let vm = this
    setTimeout(function() {
      //要延時執行的代碼
      vm.setData({
        spinShow: false
      })
      var res = (wx.getStorageSync('logs') || []).map(log => {
        return util.formatTime(new Date(log))
      });
      var tmpArr = vm.data.logs;
      tmpArr.push.apply(tmpArr, res);
      vm.setData({
        logs: tmpArr
      })
      vm.loadMore = true
    }, 3000) //延遲時間 這裏是3秒
  },
  // 下拉刷新
  onPullDownRefresh: function() {
    this.setData({
      spinShow: true
    })
    this.clearCache();
    this.getArticles(0); //第一次加載數據
  },
  // 頁面上拉觸底事件(上拉加載更多)
  onReachBottom: function() {
    page++;
    if (!this.allLoaded) {
      if (page > totalPages - 1) {
        this.setData({
          loadMore: false,
          loadMoreTip: '沒有更多了',
          allLoaded: true // 若數據已所有獲取完畢
        })
      } else {
        this.setData({
          loadMore: true,
          loadMoreTip: '加載中',
          allLoaded: false // 若數據未獲取完畢
        })
        this.getArticles(page); //後臺獲取新數據並追加渲染
      }
    } else {
      this.setData({
        loadMore: false,
        loadMoreTip: '沒有更多了',
        allLoaded: false // 若數據未獲取完畢
      })
    }
  },
  // 清緩存
  clearCache: function() {
    page = 0; //分頁標識歸零
    this.setData({
      logs: [] //文章列表數組清空
    });
  },
})

list.wxss:

.loading{
    display: inline-block;
    margin-right: 12px;
    vertical-align: middle;
    width: 20px;
    height: 20px;
    background: transparent;
    border-radius: 50%;
    border: 2px solid #2d8cf0;
    border-color: #2d8cf0 #2d8cf0 #2d8cf0 transparent;
    animation: loading-spin 0.6s linear;
    animation-iteration-count: infinite;
}

這裏下拉的效果沒作處理,上拉加載效果也比較粗糙。能夠根據項目要求再進行美觀優化,例如你能夠本身在下拉時增長下拉到底、鬆開刷新、刷新中....等動態效果。

若是,最開始,你在看本篇文章時,一步一步跟着作,那麼你也將獲得一個小程序,實現的最終效果,以下圖:

微信小程序 效果圖.gif

參考資料

微信開放文檔 你的第一個小程序
微信開放文檔 小程序配置
微信開放文檔 小程序目錄結構
微信開放文檔 組件
微信開放文檔 swiper 滑塊視圖容器

快速上手 - iView Weapp

安利向:用Visual Studio Code編寫微信小程序
vscode 小程序開發插件

小程序入坑(一)list列表以及item詳情頁,json傳送時間戳轉換成年月日

小程序-列表渲染

微信小程序 下拉刷新/上拉加載更多 (上拉加載更多怎麼實現)

微信小程序實現列表頁面及上拉加載功能

相關文章
相關標籤/搜索