微信小程序開發06-一個業務頁面的完成

前言

接上文:微信小程序開發05-日曆組件的實現css

github地址:https://github.com/yexiaochai/wxdemohtml

這裏來講一說咱們的理念,咱們也學習小程序開發有一週多了,從近期的使用上來講,小程序能夠做爲底層,可是缺乏一個框架層,這個框架層須要提供:前端

① 組件庫ios

② 更好的代碼組織方式,也就是讓咱們能夠作到輕鬆的組件化開發git

咱們從最開始到如今,都在沿着這個方向去分解小程序學習,其實小程序自己的東西差很少了,可是咱們代碼過程當中有時候卻越高越複雜,多了不少封裝,其實這全部的複雜都是爲了設置一個基本的架構,一個標準的開發模式,讓後面寫業務代碼的同窗能更高效的寫代碼,通過一年多的發展,事實上這種較爲成熟的框架已經有了,好比咱們正在使用的:github

https://tencent.github.io/wepy/ajax

可是,能夠看到小程序基本仍是原生JS,這實際上是個很是好的學習整理機會,因此我這邊一步步和你們對小程序進行了拆分,指望能造成一套還能用的雛形,幫助你們理解,因此咱們繼續今天的學習吧,爲了下降單頁面難度,咱們將首頁進行下改造。小程序

首頁

首頁作了一點改造,變成了這個樣式了:後端

這裏須要三個點擊時間點,由於日曆組件,咱們昨天就作好了,而他這個出發日期事實上就是咱們日曆組件的selecedDate,處理這塊邏輯:微信小程序

 1 <template name="searchbox">
 2   <view class="c-row search-line" data-flag="start">
 3     <view class="c-span3">
 4       出發</view>
 5     <view class="c-span9 js-start search-line-txt">
 6       請選擇出發地</view>
 7   </view>
 8   <view class="c-row search-line" data-flag="arrive">
 9     <view class="c-span3">
10       到達</view>
11     <view class="c-span9 js-arrive search-line-txt">
12       請選擇到達地</view>
13   </view>
14   <view class="c-row search-line" data-flag="arrive">
15     <view class="c-span3">
16       出發日期</view>
17     <view class="c-span9 js-arrive search-line-txt">
18       {{calendarSelectedDate || '請選擇出發日期'}} </view>
19   </view>
20   <view class="c-row " data-flag="arrive">
21     <span class="btn-primary full-width js_search_list">查詢</span>
22   </view>
23 </template>
View Code
1 <view class="c-row search-line" data-flag="arrive">
2   <view class="c-span3">
3     出發日期</view>
4   <view class="c-span9 js-arrive search-line-txt">
5     {{calendarSelectedDate || '請選擇出發日期'}} </view>
6 </view>

點擊時候咱們彈出咱們的日曆,這個時候咱們日曆模塊釋放一個事件顯示日曆:

PS:template不與頁面級別WXML共享一個做用域,因此我暫時都採用的include引入

 1 <view class="c-row search-line" data-flag="start">
 2   <view class="c-span3">
 3     出發</view>
 4   <view class="c-span9 js-start search-line-txt">
 5     請選擇出發地</view>
 6 </view>
 7 <view class="c-row search-line" data-flag="arrive">
 8   <view class="c-span3">
 9     到達</view>
10   <view class="c-span9 js-arrive search-line-txt">
11     請選擇到達地</view>
12 </view>
13 <view class="c-row search-line" data-flag="arrive" ontap="showCalendar">
14   <view class="c-span3">
15     出發日期</view>
16   <view class="c-span9 js-arrive search-line-txt">
17     {{calendarSelectedDateStr}}</view>
18 </view>
19 <view class="c-row " data-flag="arrive">
20   <span class="btn-primary full-width js_search_list">查詢</span>
21 </view>
22 <include src="./mod/calendar.wxml" />
23 <include src="../../utils/abstract-page.wxml" />
View Code
1 <view class="c-row search-line" data-flag="arrive" ontap="showCalendar">
2   <view class="c-span3">
3     出發日期</view>
4   <view class="c-span9 js-arrive search-line-txt">
5     {{calendarSelectedDateStr}}</view>
6 </view>
 1 /*
 2 事實上一個mod就只是一個對象,只不過爲了方便拆分,將對象分拆成一個個的mod
 3 一個mod對應一個wxml,可是共享外部的css,暫時如此設計
 4 全部日曆模塊的需求所有再此實現
 5 */
 6 const util = require('../../../utils/util.js')
 7 
 8 let selectedDate = new Date();
 9 
10 module.exports = {
11   showCalendar: function () {
12     this.setData({
13       isCalendarShow: ''
14     });
15   },
16   onCalendarDayTap: function (e) {
17     let data = e.detail;
18     var date = new Date(data.year, data.month, data.day);
19     console.log(date)
20     this.setData({
21       calendarSelectedDate: date,
22       calendarSelectedDateStr: util.dateUtil.format(date, 'Y年M月D日')
23     });
24   },
25   data: {
26     isCalendarShow: 'none',
27     calendarDisplayMonthNum: 2,
28     calendarDisplayTime: new Date(),
29     calendarSelectedDate: selectedDate,
30     calendarSelectedDateStr: util.dateUtil.format(selectedDate, 'Y年M月D日')
31   }
32 }

顯然,這裏的日曆這樣擺設有點醜,咱們這裏將其封裝成一個彈出層,因此咱們這裏再作一個容器類組件,專門用於裝載頁面樣式用:

1 <view class="cm-modal " style="z-index: {{uiIndex}}; position: fixed; display: {{isShow}}; ">
2   <slot ></slot>
3 </view>
4 <view class="cm-overlay" bindtap="onMaskEvent" style="z-index: {{maskzIndex}}; display: {{isShow}}" >
5 </view>
1 <ui-container bindonContainerHide="onContainerHide" is-show="{{isCalendarShow}}" >
2     <view class="calendar-wrapper-box">
3       <view class="box-hd">
4         <text class="fl icon-back js_back "></text>
5         <text class="fr icon-next js_next"></text>
6       </view>
7       <ui-calendar bindonDayTap="onCalendarDayTap" displayTime="{{calendarDisplayTime}}" 
selectedDate
="{{calendarSelectedDate}}" displayMonthNum="{{calendarDisplayMonthNum}}"
is-show
="{{isCalendarShow}}"></ui-calendar> 8 </view> 9 </ui-container>

可是這裏也引發了其餘問題,由於引入了shadow-dom概念,個人樣式不能重用,組件內部樣式與外部是不能通訊的,可是這裏是頁面級別容器,內容的樣式確定是來源頁面的,這裏沒什麼問題,因此咱們這裏顯示的是正確的,可是我這裏想作一個出格一點的操做,我想用樣式將這裏日曆月標題換個位置:

而日曆組件和外部是不能通訊的,咱們這裏該如何處理呢,我這裏想了兩個方案:

① 設置一個全局使用的組件庫樣式,讓全部組件繼承,可是不知道這裏對性能是否有影響,由於這樣的話體積不會過小

② 小程序設計了能夠傳入組件的方法,好比咱們這裏的日曆組件咱們能夠這樣改變其樣式

1 .calendar-cm-month {
2     position: absolute;
3     top: 0;
4     height: 90rpx;
5     line-height: 90rpx;
6     width: 100%;
7     color: #00b358;
8     text-align: center;
9 }
 1 Component({
 2 externalClasses: ['ex-class'],  3   behaviors: [
 4     View
 5   ],
 6   properties: {
 7     displayMonthNum: {
 8       type: Number
 9     },
10     displayTime: {
11       type: Date
12     },
13     selectedDate: {
14       type: Date
15     }
16   },
17   data: {
18     weekDayArr: ['日', '一', '二', '三', '四', '五', '六'],
19   },
20 
21   attached: function () { 
22     //console.log(this)
23     // debugger
24   },
25   methods: {
26     onDayTap: function (e) {
27       this.triggerEvent('onDayTap', e.currentTarget.dataset)
28     }
29   }
30 })
1 <ui-container bindonContainerHide="onContainerHide" is-show="{{isCalendarShow}}" >
2     <view class="calendar-wrapper-box">
3       <view class="box-hd">
4         <text class="fl icon-back js_back "></text>
5         <text class="fr icon-next js_next"></text>
6       </view>
7       <ui-calendar ex-class="calendar-cm-month" bindonDayTap="onCalendarDayTap" 
displayTime
="{{calendarDisplayTime}}" selectedDate="{{calendarSelectedDate}}"
displayMonthNum
="{{calendarDisplayMonthNum}}" is-show="{{isCalendarShow}}"></ui-calendar> 8 </view> 9 </ui-container>

具體各位去github上查看,總而言之,咱們的頁面變成了這個樣子了:

PS:這裏發現一個不知道是否是坑點的點,咱們這裏屬性傳遞的是一個date對象,可是到了組件層之間變成了對象,不知微信底層作了什麼:

calendarDisplayTime: new Date()

好像變成了一個空對象,這裏可能發生的狀況是,通過傳遞的日期對象會被某種特殊處理,可是具體發生了什麼事情就不知道了,這個卻引發了咱們不小的麻煩,這裏大概去翻開了一下源碼:

極有可能,小程序自己就不支持date屬性的傳遞,咱們的日曆組件能跑起來的緣由是什麼,我這裏都有點疑惑了......

並且就算以對象方式傳遞到組件的date類型都會變成莫名其妙的東西:

1     ttt: {
2       key: 'date',
3       value: selectedDate
4     },

這個特性有點使人抓不住頭腦了,這裏根據探查,頗有可能Component將date對象傳入WXML解釋時候,自動轉爲了日期字符串了,因此咱們這裏看上去是對象的東西實際上是字符串,這裏的建議是:跟組件的date傳遞,暫時所有使用字符串代替,以避免自我麻煩,而後咱們先將以前的日曆操做所有變成字符串,再爲咱們的先後按鈕加上事件:

 1 module.exports = {
 2   showCalendar: function () {
 3     this.setData({
 4       isCalendarShow: ''
 5     });
 6   },
 7   hideCalendar: function () {
 8     this.setData({
 9       isCalendarShow: 'none'
10     });
11   },
12   preMonth: function () {
13 
14     this.setData({
15       calendarDisplayTime: util.dateUtil.preMonth(this.data.calendarDisplayTime).toString()
16     });
17   },
18   nextMonth: function () {
19     this.setData({
20       calendarDisplayTime: util.dateUtil.nextMonth(this.data.calendarDisplayTime).toString()
21     });
22   },
23   onCalendarDayTap: function (e) {
24     let data = e.detail;
25     var date = new Date(data.year, data.month, data.day);
26     console.log(date)
27     this.setData({
28       isCalendarShow: 'none',
29       calendarSelectedDate: date.toString(),
30       calendarSelectedDateStr: util.dateUtil.format(date, 'Y年M月D日')
31     });
32   },
33   onContainerHide: function () {
34     this.hideCalendar();
35   },
36 
37   data: {
38     ttt: {
39       key: 'date',
40       value: selectedDate
41     },
42     isCalendarShow: '',
43     calendarDisplayMonthNum: 1,
44     calendarDisplayTime: new Date(2018, 9).toString(),
45     calendarSelectedDate: selectedDate,
46     calendarSelectedDateStr: util.dateUtil.format(new Date(selectedDate), 'Y年M月D日')
47   }
48 }

雖然看上去噁心了一點,可是老是不會出什麼明顯的問題,忍一忍吧......日期部分基本結束了,還有些小的限制沒有作上,好比哪些時段能選,哪些不能,這塊就有待各位發現吧,咱們這裏畢竟是學習,作細了很花功夫,咱們接下來作出發目的地選擇部分。

數據請求

城市列表

城市列表這裏看起來須要新開一個頁面,可是我這裏想作在一個頁面中,考慮篇幅,咱們使用彈出層容器組件看而且儘可能削弱一些特性,幾天下來別說寫的還有些累......

這個又做爲首頁的一個模塊而存在:

 1 <view style="display: {{isCityShow}}; " class="city-wrapper"  >
 2     <view class="city-list">
 3         <view class="list-name">A</view>
 4         <view class="list-item">成都</view>
 5         <view class="list-item">成都</view>
 6         <view class="list-item">成都</view>
 7         <view class="list-item">成都</view>
 8         <view class="list-item">成都</view>
 9         <view class="list-item">成都</view>
10     </view>
11     <view class="city-list">
12         <view class="list-name">A</view>
13         <view class="list-item">成都</view>
14         <view class="list-item">成都</view>
15         <view class="list-item">成都</view>
16         <view class="list-item">成都</view>
17         <view class="list-item">成都</view>
18         <view class="list-item">成都</view>
19     </view>
20 </view>
 1 /*
 2 事實上一個mod就只是一個對象,只不過爲了方便拆分,將對象分拆成一個個的mod
 3 一個mod對應一個wxml,可是共享外部的css,暫時如此設計
 4 全部日曆模塊的需求所有再此實現
 5 */
 6 const util = require('../../../utils/util.js')
 7 
 8 let selectedDate = new Date().toString();
 9 
10 module.exports = {
11   showCitylist: function (e) {
12     let flag = e.currentTarget.dataset.flag;
13 
14     if(flag === 'start') {
15 
16     } else {
17 
18     }
19   },
20   //用於設置城市數據
21   setCityData: function (data) {
22 
23   },
24   showCity: function () {
25       this.setData({
26         isCityShow: ''
27       });
28   },
29   shideCity: function () {
30     this.setData({
31       isCityShow: 'none'
32     });
33   },
34   data: {
35     isCityShow: ''
36   }
37 }

首頁調用代碼:

 1 //獲取公共ui操做類實例
 2 const _page = require('../../utils/abstract-page.js');
 3 let modCalendar = require('./mod/calendar.js');
 4 let modCity = require('./mod/city.js');
 5 
 6 //獲取應用實例
 7 const app = getApp()
 8 
 9 Page(_page.initPage({
10   data: {
11   },
12   // methods: uiUtil.getPageMethods(),
13   methods: {
14   },
15   onShow: function () {
16     global.sss = this;
17     let scope = this;
18   },
19   onLoad: function () {
20     // this.setPageMethods();
21   }
22 }, {
23   modCalendar: modCalendar,
24   modCity: modCity
25 }))

這裏咱們開始有數據請求模塊了,小程序使用這個接口請求數據,這裏比較尷尬的是他要設置域名白名單:

wx.request(OBJECT)

而咱們使用的是測試帳號沒有能夠設置的地方,因此咱們仍是去申請個小程序帳號吧...配置成功,咱們繼續代碼:

能夠看到數據請求已經回來了,可是咱們通常來講一個接口不止會用於一個地方,每次從新寫好像有些費事,加之我這裏想將重複的請求緩存起來,因此咱們這裏封裝一套數據訪問層出來

數據緩存(持久層)

以前在瀏覽器中,咱們通常使用localstorage存儲一些不太更改的數據,微信裏面提供了接口處理這一切:

wx.setStorage(OBJECT)

咱們這裏須要對其進行簡單封裝,便與後面更好的使用,通常來講有緩存就必定要有過時,因此咱們動態給每一個緩存對象增長一個過時時間:

  1 class Store {
  2   constructor(opts) {
  3     if(typeof opts === 'string') this.key = opts;
  4     else Object.assign(this, opts);
  5 
  6     //若是沒有傳過時時間,則默認30分鐘
  7     if(!this.lifeTime) this.lifeTime = 1;
  8 
  9     //本地緩存用以存放全部localstorage鍵值與過時日期的映射
 10     this._keyCache = 'SYSTEM_KEY_TIMEOUT_MAP';
 11 
 12   }
 13   //獲取過時時間,單位爲毫秒
 14   _getDeadline() {
 15     return this.lifeTime * 60 * 1000;
 16   }
 17 
 18   //獲取一個數據緩存對象,存能夠異步,獲取我同步便可
 19   get(sign){
 20     let key = this.key;
 21     let now = new Date().getTime();
 22     var data = wx.getStorageSync(key);
 23     if(!data) return null;
 24     data = JSON.parse(data);
 25     //數據過時
 26     if (data.deadLine < now) {
 27       this.removeOverdueCache();
 28       return null;
 29     }
 30 
 31     if(data.sign) {
 32       if(sign === data.sign) return data.data;
 33       else return null;
 34     }
 35     return null;
 36   }
 37 
 38   /*產出頁面組件須要的參數
 39   sign 爲格式化後的請求參數,用於同一請求不一樣參數時候返回新數據,好比列表爲北京的城市,後切換爲上海,會判斷tag不一樣而更新緩存數據,tag至關於簽名
 40   每一鍵值只會緩存一條信息
 41   */
 42   set(data, sign) {
 43     let timeout = new Date();
 44     let time = timeout.setTime(timeout.getTime() + this._getDeadline());
 45     this._saveData(data, time, sign);
 46   }
 47   _saveData(data, time, sign) {
 48     let key = this.key;
 49     let entity = {
 50       deadLine: time,
 51       data: data,
 52       sign: sign
 53     };
 54     let scope = this;
 55 
 56     wx.setStorage({
 57       key: key,
 58       data: JSON.stringify(entity),
 59       success: function () {
 60         //每次真實存入前,須要往系統中存儲一個清單
 61         scope._saveSysList(key, entity.deadLine);
 62       }
 63     });
 64   }
 65   _saveSysList(key, timeout) {
 66     if (!key || !timeout || timeout < new Date().getTime()) return;
 67     let keyCache = this._keyCache;
 68     wx.getStorage({
 69       key: keyCache,
 70       complete: function (data) {
 71         let oldData = {};
 72         if(data.data) oldData = JSON.parse(data.data);
 73         oldData[key] = timeout;
 74         wx.setStorage({
 75           key: keyCache,
 76           data: JSON.stringify(oldData)
 77         });
 78       }
 79     });
 80   }
 81   //刪除過時緩存
 82   removeOverdueCache() {
 83     let now = new Date().getTime();
 84     let keyCache = this._keyCache;
 85     wx.getStorage({
 86       key: keyCache,
 87       success: function (data) {
 88         if(data && data.data) data = JSON.parse(data.data);
 89         for(let k in data) {
 90           if(data[k] < now) {
 91             delete data[k];
 92             wx.removeStorage({key: k, success: function(){}});
 93           }
 94         }
 95         wx.setStorage({
 96           key: keyCache,
 97           data: JSON.stringify(data)
 98         });
 99       }
100     });
101   }
102 
103 }
104 
105 module.exports = Store

這個類的使用也很是簡單,這裏舉個例子:

1 sss = new global.Store({key: 'qqq', lifeTime: 1})
2 sss.set({a: 1}, 2)
3 sss.get()//由於沒有祕鑰會是null
4 sss.get(2)//sss.get(2)

這個時候咱們開始寫咱們數據請求的類:

首先仍是實現了一個抽象類和一個業務基類,而後開始在業務層請求數據:

 1 class Model {
 2   constructor() {
 3     this.url = '';
 4     this.param = {};
 5     this.validates = [];
 6   }
 7   pushValidates(handler) {
 8     if (typeof handler === 'function') {
 9       this.validates.push(handler);
10     }
11   }
12   setParam(key, val) {
13     if (typeof key === 'object') {
14       Object.assign(this.param, key);
15     } else {
16       this.param[key] = val;
17     }
18   }
19   //@override
20   buildurl() {
21     return this.url;
22   }
23   onDataSuccess() {
24   }
25   //執行數據請求邏輯
26   execute(onComplete) {
27     let scope = this;
28     let _success = function(data) {
29       let _data = data;
30       if (typeof data == 'string') _data = JSON.parse(data);
31 
32       // @description 開發者能夠傳入一組驗證方法進行驗證
33       for (let i = 0, len = scope.validates.length; i < len; i++) {
34         if (!scope.validates[i](data)) {
35           // @description 若是一個驗證不經過就返回
36           if (typeof onError === 'function') {
37             return onError.call(scope || this, _data, data);
38           } else {
39             return false;
40           }
41         }
42       }
43 
44       // @description 對獲取的數據作字段映射
45       let datamodel = typeof scope.dataformat === 'function' ? scope.dataformat(_data) : _data;
46 
47       if (scope.onDataSuccess) scope.onDataSuccess.call(scope, datamodel, data);
48       if (typeof onComplete === 'function') {
49         onComplete.call(scope, datamodel, data);
50       }
51     };
52     this._sendRequest(_success);
53   }
54 
55   //刪除過時緩存
56   _sendRequest(callback) {
57     let url = this.buildurl();
58     wx.request({
59       url: this.buildurl(),
60       data: this.param,
61       success: function success(data) {
62         callback && callback(data);
63       }
64     });
65   }
66 }
67 module.exports = Model
 1 let Model = require('./abstract-model.js');
 2 
 3 class DemoModel extends Model {
 4   constructor() {
 5     super();
 6     let scope = this;
 7     this.domain = 'https://apikuai.baidu.com';
 8     this.param = {
 9       head: {
10         version: '1.0.1',
11         ct: 'ios'
12       }
13     };
14 
15     //若是須要緩存,能夠在此設置緩存對象
16     this.cacheData = null;
17 
18     this.pushValidates(function(data) {
19       return scope._baseDataValidate(data);
20     });
21   }
22 
23   //首輪處理返回數據,檢查錯誤碼作統一驗證處理
24   _baseDataValidate(data) {
25     if (typeof data === 'string') data = JSON.parse(data);
26     if (data.data) data = data.data;
27     if (data.errno === 0) return true;
28     return false;
29   }
30 
31   dataformat(data) {
32     if (typeof data === 'string') data = JSON.parse(data);
33     if (data.data) data = data.data;
34     if (data.data) data = data.data;
35     return data;
36   }
37 
38   buildurl() {
39     return this.domain + this.url;
40   }
41 
42   getSign() {
43     let param = this.getParam() || {};
44     return JSON.stringify(param);
45   }
46   onDataSuccess(fdata, data) {
47     if (this.cacheData && this.cacheData.set)
48       this.cacheData.set(fdata, this.getSign());
49   }
50 
51   //若是有緩存直接讀取緩存,沒有才請求
52   execute(onComplete, ajaxOnly) {
53     let data = null;
54     if (!ajaxOnly && this.cacheData && this.cacheData.get) {
55       data = this.cacheData.get(this.getSign());
56       if (data) {
57         onComplete(data);
58         return;
59       }
60     }
61     super.execute(onComplete);
62   }
63 
64 }
65 
66 class CityModel extends DemoModel {
67   constructor() {
68     super();
69     this.url = '/city/getstartcitys';
70   }
71 }
72 
73 module.exports = {
74   cityModel: new CityModel
75 
76 }
業務基類

接下來是實際調用代碼:

1 let model = models.cityModel;
2 model.setParam({
3   type: 1
4 });
5 model.execute(function(data) {
6   console.log(data);
7   debugger;
8 });

數據便請求結束了,有了這個類咱們能夠作很是多的工做,好比:

① 前端設置統一的錯誤碼處理邏輯

② 前端打點,統計全部的接口響應狀態

③ 每次請求相同參數作數據緩存

④ 這個對於錯誤處理很關鍵,通常來講前端出錯很大可能都是後端數據接口字段有變化,而這種錯誤是比較難尋找的,若是我這裏作一個統一的收口,每次數據返回記錄全部的返回字段的標誌上報呢,就以這個城市數據爲例,咱們能夠這樣作:

 1 class CityModel extends DemoModel {
 2   constructor() {
 3     super();
 4     this.url = '/city/getstartcitys';
 5   }
 6   //每次數據訪問成功,錯誤碼爲0時皆會執行這個回調
 7   onDataSuccess(fdata, data) {
 8     super.onDataSuccess(fdata, data);
 9     //開始執行自我邏輯
10     let o = {
11       _indate: new Date().getTime()
12     };
13     for(let k in fdata) {
14       o[k] = typeof fdata[k];
15     }
16     //執行數據上報邏輯
17     console.log(JSON.stringify(o));
18   }
19 }

這裏就會輸出如下信息:

{"_indate":1533436847778,"cities":"object","hots":"object","total":"number","page":"string"}

若是對數據要求很是嚴苛,對某些接口作到字段層面的驗證,那麼加一個Validates驗證便可,這樣對接口的控制會最大化,就算哪次出問題,也能很好從數據分析系統之中能夠查看到問題所在,若是我如今想要一個更爲具體的功能呢?我想要首次請求一個接口時便將其數據記錄下來,第二次便再也不請求呢,這個時候咱們以前設計的數據持久層便派上了用處:

 1 let Store = require('./abstract-store.js');
 2 
 3 class CityStore extends Store {
 4   constructor() {
 5     super();
 6     this.key = 'DEMO_CITYLIST';
 7     //30分鐘過時時間
 8     this.lifeTime = 30;
 9   }
10 }
11 
12 module.exports = {
13   cityStore: new CityStore
14 }
 1 class CityModel extends DemoModel {
 2   constructor() {
 3     super();
 4     this.url = '/city/getstartcitys';
 5     this.cacheData = Stores.cityStore;
 6   }
 7   //每次數據訪問成功,錯誤碼爲0時皆會執行這個回調
 8   onDataSuccess(fdata, data) {
 9     super.onDataSuccess(fdata, data);
10     //開始執行自我邏輯
11     let o = {
12       _indate: new Date().getTime()
13     };
14     for(let k in fdata) {
15       o[k] = typeof fdata[k];
16     }
17     //執行數據上報邏輯
18     console.log(JSON.stringify(o));
19   }
20 }

這個時候第二次請求時候便會直接讀取緩存了

接下來即可以回到咱們的頁面渲染邏輯了,這個時候就變得很是簡單了:

 1 <view style="display: {{isCityShow}}; " class="city-wrapper">
 2   <block wx:for="{{cityData}}" wx:key="k">
 3     <view class="city-list">
 4       <block wx:for="{{item}}" wx:key="kk" wx:for-index="key" wx:for-item="value">
 5         <view class="list-name">{{key}}</view>
 6         <block wx:for="{{value}}" wx:key="kkk" wx:for-index="i" wx:for-item="v">
 7           <view class="list-item" data-cnname="{{v.name}}" data-id="{{v.regionid}}">{{v.cnname}}</view>
 8         </block>
 9       </block>
10     </view>
11   </block>
12 </view>
 1 //用於設置城市數據
 2   setCityData: function(data) {
 3     data = data.cities;
 4     let citys = {}, sortCitys = [];
 5     let k, gname, name, i, tmp = {}, index;
 6 
 7     //首先處理每一個name生成惟一K
 8     for (k in data) {
 9       name = data[k].name;
10       if (!name) {
11         continue;
12       }
13       gname = name[0].toUpperCase();
14       if (!citys[gname]) citys[gname] = [];
15       citys[gname].push(data[k]);
16     }
17 
18     for (i = 65; i < 91; i++) {
19       tmp = {};
20       tmp[String.fromCharCode(i)] = [];
21       sortCitys.push(tmp);
22     }
23 
24     for (k in citys) {
25       index = k.charCodeAt() - 65;
26       tmp = {};
27       tmp[k] = citys[k];
28       sortCitys[index] = tmp;
29     }
30 
31     this.setData({
32       cityData: sortCitys,
33       isCityShow: ''
34     });
35   },

而後咱們這裏爲組件綁定事件等就比較簡單了,你們能夠本身看github,因而咱們首頁的功能便完成了:

通過一個多星期的學習,咱們慢慢的完成了咱們的首頁,好像也就幾個元素,可是後面的一切卻不簡單啊,咱們明天繼續完成list頁面邏輯,便開始總結小程序開發

相關文章
相關標籤/搜索