无码日韩精品无码国产_一级做a爰片久久毛片潮喷_国产欧美国日产_久久9热re这里只有国产中文精品6_每天将为您更新成人影视在线看免费观看

Menu
小程序資訊
小程序資訊
微信小程序開發(fā)系列分析《二》數(shù)據(jù)層
時(shí)間:2016-10-18 15:55:00
本文分三塊來講,網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求,文件操作,本地?cái)?shù)據(jù)操作。涉及到的示例代碼地址:https://github.com/jsongo/weapp-tutorial-3

1、網(wǎng)絡(luò)請(qǐng)求

(1)需要一個(gè)數(shù)據(jù)接口來測(cè)試
上篇文章中的數(shù)據(jù),我們是寫死在page的data里的。實(shí)際應(yīng)用中肯定不會(huì)這么干,只能是從后臺(tái)請(qǐng)求,或從本地存儲(chǔ)中獲取。
微信提供了一個(gè)接口用來發(fā)起請(qǐng)求:wx.request。而且它發(fā)起的請(qǐng)求,官方文檔中說,只能是https請(qǐng)求,且一個(gè)微信小程序,同時(shí)只能有5個(gè)網(wǎng)絡(luò)請(qǐng)求連接。

我們來修改一下上篇文章中用到的例子,我們把數(shù)據(jù)改成從36Kr那里獲取。稍微研究下36Kr網(wǎng)站的頁面,就會(huì)發(fā)現(xiàn)一個(gè)小接口,用來拉取列表數(shù)據(jù):
API:Get http://36kr.com/api/info-flow/main_site/posts?b_id=5053833&per_page=20&_=1475166251729
url參數(shù):bid表示上次列表拉到第幾條,那條的id;per_page表示要拉取多少條;最后的下劃線表示當(dāng)前的時(shí)間戳,這個(gè)可以省略。
返回:json格式的數(shù)據(jù),結(jié)構(gòu)如下

36Kr返回列表數(shù)據(jù)
其中,當(dāng)code為0時(shí),表示沒有error,這時(shí)拿到的response.data.items就是我們要的數(shù)據(jù)列表,我們只取每一項(xiàng)里的幾個(gè)數(shù)據(jù)就可以了。請(qǐng)求的地址不是https,不過可以發(fā)現(xiàn),我們把地址改成https,也可以請(qǐng)求到數(shù)據(jù),說明36Kr后臺(tái)做了https的接入。

(2)發(fā)起請(qǐng)求
wx.request的用法其實(shí)跟ajax的調(diào)用很像。

wx.request({
  url: url,
  data: {},
  header: {
      'Content-Type': 'application/json'
  },
  success: function(res) {
    … // use res.data
  }
})
它有幾個(gè)主要的參數(shù):url指定請(qǐng)求地址;data帶上請(qǐng)求的數(shù)據(jù),可能是json數(shù)據(jù)也可以是字符串;header設(shè)置請(qǐng)求的頭部信息,如上面所示;method指定請(qǐng)求的方式,默認(rèn)是GET,其它值有:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT;另外,success用來指定請(qǐng)求成功的回調(diào),fail是失敗的回調(diào),還有一個(gè)complete,成功或失敗都會(huì)回調(diào)。

以上代碼中,在success回調(diào)里拿到res是一個(gè)json數(shù)據(jù),格式如:{data: xxx} ,res.data就可以拿到服務(wù)器返回的數(shù)據(jù)。完整代碼可以參考github上的pages/index/index.js文件。

開發(fā)工具之前的破解版本,其實(shí)是發(fā)不了網(wǎng)絡(luò)請(qǐng)求的。因?yàn)槲⑿旁诠ぞ呃镒隽艘恍┌踩拗疲赃@里為了開發(fā),我們得再去破解開發(fā)工具。研究了下工具源碼,找到一個(gè)地方會(huì)對(duì)網(wǎng)絡(luò)請(qǐng)求的地址做驗(yàn)證的,把它改掉就Ok。最新工具破解方法參考https://github.com/jsongo/weApp-ide ,有興趣的讀者可以到app.nw/app/dist/weapp/appservice/asdebug.js 文件中,找到下面這行代碼,把if條件改掉就可以用了,比較簡單。

破解網(wǎng)絡(luò)請(qǐng)求限制

(3)demo功能分析
簡單幾句話分析一下我們的36Kr新聞列表的demo。功能也挺簡單,打開時(shí)從網(wǎng)絡(luò)上請(qǐng)求36Kr的數(shù)據(jù)顯示成一個(gè)列表,點(diǎn)擊列表的每一項(xiàng)都可以進(jìn)入查看這篇文章的正文內(nèi)容(只是個(gè)demo,所以就沒有去取內(nèi)容,直接拿每個(gè)列表項(xiàng)的summary字段去當(dāng)正文)。列表頁在頂部下拉可以刷新列表,在最底部往上滑可以加載更多。

破解網(wǎng)絡(luò)請(qǐng)求限制

(4)demo數(shù)據(jù)分析
列表的生成邏輯跟上篇文章的一樣,只是數(shù)據(jù)的來源不同而已。主要代碼的結(jié)構(gòu)如下:

主代碼
data里定義了兩個(gè)屬性,一個(gè)是news數(shù)組,用來綁定列表數(shù)據(jù);refresh,用來決定上方的loading區(qū)域是否顯示,只有用戶在頂部下拉的時(shí)候,才會(huì)顯示最頂部的loading...區(qū)域,view中通過<view wx:if="{{refresh}}”>來綁定是否顯示,在<scroll-view>的bindscrolltoupper函數(shù)中用this.setData({refresh: true}) 把它顯示出來。然后在數(shù)據(jù)請(qǐng)求回來的complete方法中,再把它隱藏掉。這樣就簡單的實(shí)現(xiàn)了,下拉刷新的功能。當(dāng)然體驗(yàn)不是很好,讀者可以自己想慢慢地優(yōu)化軟件的體驗(yàn)問題。

繼續(xù)分析下我們的demo代碼。
大家可能注意到了里定義了一個(gè)loading的屬性,它是用來記錄當(dāng)前是否是在請(qǐng)求中,如果是就放棄請(qǐng)求。這主要用來防止同一時(shí)間發(fā)出多個(gè)請(qǐng)求。用戶幾個(gè)很快的動(dòng)作可能會(huì)觸發(fā)了幾次數(shù)據(jù)加載,比如用戶在頂部下拉的時(shí)候,網(wǎng)絡(luò)不是很好,數(shù)據(jù)還沒返回,用戶可能會(huì)連續(xù)快速下拉好多次,這時(shí)用loading這個(gè)標(biāo)識(shí)就可以過濾掉這些多余的操作。它在請(qǐng)求發(fā)出的之前設(shè)置為true,請(qǐng)求回來的時(shí)候,在complete回調(diào)中設(shè)置為false。

onLoad是生命周期函數(shù),只做了一件事件,就是調(diào)用reqData方法發(fā)起第一屏列表數(shù)據(jù)的請(qǐng)求。
bindItemTap綁定了每個(gè)新聞列表項(xiàng)的點(diǎn)擊事件,點(diǎn)擊后,把當(dāng)前的數(shù)據(jù)傳入到App的globalData里,再切換到內(nèi)容詳情頁面,然后從globalData取出數(shù)據(jù)來顯示。在官方的文檔中沒有找到頁面間傳遞數(shù)據(jù)的其它辦法,筆者只想到兩種方式,一是通過剛討論的globalData,另一個(gè)是通過本地存儲(chǔ)來傳遞,這個(gè)在下面會(huì)再討論。

reqData方法封裝了數(shù)據(jù)請(qǐng)求的過程,第三個(gè)參數(shù)用來指定是append(底部加載更多)還是refresh(頂部下拉刷新),因?yàn)檫@兩個(gè)接口的請(qǐng)求地址等其它處理過程有些不太一樣。
formatData函數(shù),封裝了把請(qǐng)求返回的數(shù)據(jù)轉(zhuǎn)換成我們列表中用得到的數(shù)據(jù),修改一些字段,拼裝出每一個(gè)列表項(xiàng)數(shù)據(jù)。
renderData函數(shù)是我們重點(diǎn)要討論的,先看看實(shí)現(xiàn),30幾行,也不多:

renderData函數(shù)代碼
上方最開始的兩個(gè)if,用來驗(yàn)證請(qǐng)求返回的數(shù)據(jù)。然后用formatData把它們轉(zhuǎn)化成我們可以用的數(shù)據(jù)列表。接著對(duì)appendOrRefresh進(jìn)行判斷,如果是1的話,就是refresh;2的話,即為append,即在底部上滑時(shí)加載更多。都不是的話,就執(zhí)行默認(rèn)的加載第一屏數(shù)據(jù),這個(gè)最簡單,只要setData把數(shù)據(jù)設(shè)置到綁定列表的news這個(gè)數(shù)據(jù)段就可以了。而且對(duì)于加載更多,和刷新,這兩個(gè)動(dòng)作,則稍微復(fù)雜些。

先來看下appendOrRefresh,就是refresh,頂部下拉刷新。讀者思考一下,其實(shí)就是把新數(shù)據(jù),追加到原this.data.news列表里,由于index發(fā)生了變化,所以每一項(xiàng)的數(shù)據(jù)也會(huì)跟著變化,微信的文檔中沒有給出相應(yīng)的解決方案,只能是整體更新整個(gè)列表,這會(huì)造成整個(gè)列表界面的整體刷新,效率會(huì)很低,希望后續(xù)MINA框架會(huì)有優(yōu)化。當(dāng)然,聰明的讀者可能會(huì)想到優(yōu)化的方案,其實(shí)可以在這個(gè)時(shí)候,把新數(shù)據(jù)列表的前10項(xiàng)設(shè)置給this.data.news,反正用戶是在列表的頂部,第一屏也看不完這么多條。其它的數(shù)據(jù)則先存儲(chǔ)到本地,等用戶往下滑動(dòng)的時(shí)候,再去檢查本地存儲(chǔ)是否有需要的數(shù)據(jù)。這要用戶去做一些標(biāo)記的邏輯,下面會(huì)講到相關(guān)邏輯的實(shí)現(xiàn)。

再來看看底部上滑時(shí)加載更多,用過react的讀者應(yīng)該都知道facebook提供了Immutable庫來實(shí)現(xiàn)局部刷新,但這個(gè)在微信小程序的開發(fā)中還不知道怎么整合。不過沒關(guān)系,我們有辦法。官方文檔中有一句話提示了一種解決方法,它上面的例子是:

    this.setData({
      'array[0].text':'changed data'
    })
看到這個(gè),有沒有突然靈光一閃的感覺?沒錯(cuò),setData可以對(duì)數(shù)據(jù)進(jìn)行局部的更新。所以我們的問題就得到了解決,其實(shí)也就是往this.data.news數(shù)組追加新數(shù)據(jù)而且不引起系統(tǒng)覺得整個(gè)數(shù)據(jù)都變了。如果只是簡單的setData({news: newArr}) 這樣用newArr來賦值,肯定不行,因?yàn)樵趦?nèi)存的地址都變了。這里要實(shí)現(xiàn)的核心目標(biāo)是,保持news在內(nèi)存中的地址不變,MINA才不會(huì)去刷新整個(gè)列表。這個(gè)道理可能用過react的讀者會(huì)比較好理解一些。。這里筆者就假裝所有的讀者都已經(jīng)理解了(不理解的話就跳過吧,以后再回來看吧)。我們可以做一個(gè)for循環(huán),用this.setData方法傳入'array[xxx]': newItemXXX就行了。不過js里對(duì)json數(shù)據(jù)賦值時(shí),key是不能用'array['+index+']'這樣的方式來做的,會(huì)報(bào)錯(cuò)。所以可以像上面的代碼一樣用es6的語法,用[ ]中括號(hào)把key包起來。也或者也可以在上面定義一個(gè)變量newData,用newData['array[' + index + ']'] = newItemXXX這樣的方式來賦值也行,再this.setData(newData)就可以了。
這個(gè)知識(shí)點(diǎn)講的比較細(xì)些,有點(diǎn)啰嗦了。這一系列的文章是針對(duì)各種基礎(chǔ)的開發(fā)者,所以講得詳細(xì)些。

(5)接入列表刷新的接口
現(xiàn)在頂部下拉實(shí)現(xiàn)更新,就差一個(gè)接口了。上面第一屏的數(shù)據(jù)和底部上滑加載更多的數(shù)據(jù),我們有同一個(gè)接口可以獲取,那刷新呢?

于是我們?cè)偃?6Kr網(wǎng)站上找找,可惜的是沒找到相應(yīng)的刷新接口,不過找到了另一個(gè)替代品:
API: Get http://36kr.com/api/newsflash?b_id=26330&per_page=20&_=1475202501776
參數(shù)跟返回,跟本文介紹的第一個(gè)接口一樣,不再贅述。這個(gè)接口用來取新聞快訊,沒有圖片,比較麻煩,本文只做demo演示,所以這些都不是重點(diǎn),我們就暫且拿接口里的user的頭像來當(dāng)新聞圖片吧。36Kr網(wǎng)如若看到本文,希望不要計(jì)較這些,這些接口誰都可以從網(wǎng)頁請(qǐng)求中很容易得得到,本文只用它們來做一些demo演示,不做任何商業(yè)用途。當(dāng)然如果讀者本人有后臺(tái)開發(fā)的能力,也可以自己寫個(gè)接口來做demo的數(shù)據(jù)源。

到這里,我們已經(jīng)實(shí)現(xiàn)了大部分功能,通過綁定事件來實(shí)現(xiàn)滑到詢問時(shí),加載各種數(shù)據(jù),整個(gè)流程,從打開->加載數(shù)據(jù)->顯示列表->用戶操作時(shí)刷新或加載更多數(shù)據(jù)->點(diǎn)擊查看正文,小麻雀就已經(jīng)長了整個(gè)雛形了。

2、websocket和文件上傳下載

本文重點(diǎn)在數(shù)據(jù)層,websocket的知識(shí)點(diǎn),在后面有一篇文章會(huì)專門討論,這里先簡單一句話帶過。
而文件也是數(shù)據(jù),在本文的討論范圍之內(nèi),下面分析兩個(gè)基本操作。

(1)文件上傳
其實(shí)也是一個(gè)post請(qǐng)求,微信封裝了兩個(gè)接口,wx.chooseImage選擇文件,和wx.uploadFile指定上傳的參數(shù),這兩個(gè)接口一起完成了文件上傳的動(dòng)作。貼一個(gè)官方給的demo讀者自己看就行了,很簡單,也沒什么好分析的。要測(cè)試的小伙伴需要自己搭個(gè)后臺(tái)并像網(wǎng)頁正常的form文件上傳一樣,接收相應(yīng)的參數(shù)和file data再寫入文件就ok。


(2)文件下載
調(diào)用wx.downloadFile接口,指定路徑和文件的類型,就可以拿到文件,這時(shí)微信會(huì)幫你把文件保存在一個(gè)臨時(shí)的目錄,小程序退出時(shí)它就會(huì)被清掉。如果這是一個(gè)比較重要的文件,以后還會(huì)用的話,請(qǐng)開發(fā)者一定要調(diào)用wx.saveFile方法把文件保存到比較持久目錄,微信不會(huì)隨意把它清理掉。保存時(shí)也不需要指定要保存到哪里,微信會(huì)在保存成功后,在回調(diào)里傳回給你它保存的路徑。

downloadFile的文件只能是image/audio/video這三種類型,即圖片、音頻和視頻文件。
在開者應(yīng)用的時(shí)候,你可能會(huì)想保存登錄用戶的頭像等文件信息,這就可以用到上面的saveFile的方法,不過也要先調(diào)用wx.downloadFile先存到臨時(shí)目錄,因?yàn)閟aveFile只支持從臨時(shí)目錄保存到永久目錄。

不過在測(cè)試downloadFile的時(shí)候,發(fā)現(xiàn)success一直沒有被回調(diào),跟蹤了下代碼,發(fā)現(xiàn)到底層源碼在WeixinJSBridge.invoke(‘downloadFile’…)的時(shí)候就沒反應(yīng)了,可能要到真實(shí)的手機(jī)環(huán)境中才能使用,也或許目前的這個(gè)開發(fā)用的IDE有點(diǎn)問題。

3、本地存儲(chǔ)

也是數(shù)據(jù)緩存。微信給每個(gè)小程序分配了5M的存儲(chǔ)空間,對(duì)這個(gè)緩存的操作,其實(shí)跟H5的localStorage操作是一樣的。

微信提供了三個(gè)主要的接口, wx.setStorage(wx.setStorageSync)、wx.getStorage(wx.getStorageSync)、wx.clearStorage(wx.clearStorageSync),括號(hào)里面的是方法是同步的方法,括號(hào)外面的方法是異步讀寫的方法。這兩類方法調(diào)用時(shí)傳入的參數(shù)大體差不多,只是異步的是通過傳入回調(diào)函數(shù)的方式來取到數(shù)據(jù),而同步的方法是直接返回?cái)?shù)據(jù)。

(1)存入
wx.setStorage,參數(shù)是個(gè)json,字段有key指定存儲(chǔ)的鍵值,data指定存儲(chǔ)的值,如

wx.setStorage({key: 'name', data: 'jason'});
同時(shí) 還可以傳入success、fail和complete來取得數(shù)據(jù)或錯(cuò)誤信息。
而wx.setStorageSync比較簡單,參數(shù)是直接傳的,如:

wx.setStorageSync('name', 'jason');
存入的data數(shù)據(jù),可以是字符串,也可以是json格式的對(duì)象Object。如果存的是json,取的時(shí)候,也會(huì)是json格式的。這個(gè)用起來會(huì)非常方便。

存入的數(shù)據(jù),可以在調(diào)試工具的Storage里看到,如上圖。

(2)取出
一樣,wx.getStorage也是傳入json,字段只要帶一個(gè)key字符串就行,通過字段success回調(diào)來取得參數(shù)。
而wx.getStorageSync就非常簡單,直接就可以取到返回值。

var value = wx.getStorageSync('key');
(3)刪除
wx.clearStorage()或wx.clearStorageSync(),直接調(diào)用就成。不過調(diào)用這個(gè)方法要注意,它會(huì)清掉所有的數(shù)據(jù)。
那要怎么刪除單個(gè)key的數(shù)據(jù)呢?很簡單,就是通過setStorage或setStorageSync,把data設(shè)置成null就可以把數(shù)據(jù)清掉了,讓它不占空間就可以了。

為什么要分同步和異步呢?
1是在存儲(chǔ)的數(shù)據(jù)比較大的時(shí)候,同步方法會(huì)引起界面的卡頓,所以用異步好些,不影響界面。
2是異步方法的錯(cuò)誤處理,是fail回調(diào),出錯(cuò)一般是通過fail傳出來的。而同步方法要加上try catch才能避免程序異常中斷。
不過同步比異步在使用的時(shí)候簡單很多。如果用戶在存儲(chǔ)的數(shù)據(jù)很小的時(shí)候,基本確定不會(huì)有什么邏輯錯(cuò)誤,可以直接用同步方法。
但如果覺得你的應(yīng)用有可能會(huì)達(dá)到5M的空間的時(shí)候,再存就會(huì)拋錯(cuò),這時(shí)同步方法就要注意try catch。
咨詢
微信掃碼咨詢
電話咨詢
400-888-9358