接上文:微信小程序開發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>
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" />
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頁面邏輯,便開始總結小程序開發