上一篇是九月二十七日寫的,而這一篇我動筆的時間是十月十日(特殊的日子),中間相隔十三天——當然是因為國慶節。說老實話,這十三天里面我都沒有碰和小程序有關的東西——畢竟學習小程序的開發也只是起于興趣,而平時的工作并不會涉及與其相關的東西——但是在這十三天里,我能明顯的感受到小程序熱正在逐漸的消退,或者說大家正在逐漸以一種較為平和的姿態接受它的存在,其實這是一件好事。期待公測的到來。
接下來我就直接進入正題了,另外,文末我想和大家分享一下我的國慶節。
PS:這篇文章是接著上一篇文章 一名Android開發者的微信小程序填坑之路《上》 寫的,建議沒看過上一篇文章的同學先看一下上一篇哈~
正文
6,后臺接收 post 請求要表單?
首先問題是:我要向后臺 post 一些數據,但是后臺需要接收一個表單,我應該怎樣獲得一個表單或者將本地的數據轉換成一個表單呢?
在寫 wechat-weapp-gank 的提交干貨模塊的時候,我就遇到了這個問題。一開始我挺納悶的,明明是把后臺需要的數據都給傳過去了,結果后臺老是跟我說我的數據不對,后來我才發現是因為后臺那邊要求接收一個表單,而我傳過去的是一個 json 數據。于是我就開始了漫長的探索之旅。(就為了這一個問題,從晚上十一點多一直搞到第二天凌晨四點多。。。如果不是有一個群里有個老司機幫忙說不定就死在這個問題上了)
首先我想的是能不能把現成的 json 數據直接轉化為 form 表單?因為我已經完成了獲取要輸的信息然后把它變成了 json 數據的工作,如果能直接把 json 對象轉化為 form 對象的話我需要對程序做的改動肯定是最小的。然而遺憾的是,似乎并沒有可行的方案。(也有可能是因為我 js 功底太差吧,我確實是沒有找到相應的方法,要生成一個 form 似乎是需要 document 的,而小程序中我們并不能夠得到它)
此路不通,另覓他途。在查閱資料的過程中,我發現在 HTML 中似乎是有 這個標簽的,然后我就興沖沖的又去翻閱了一下小程序的官方文檔,果不其然,小程序還是很良心的,有這方面的描述:

然后我就興沖沖的去按照官方的介紹用 標簽來提交數據,js 里的代碼是這樣的:
formSubmit: function (event) {
wx.request({
url: Constant.BASE_URL + "/add2gank",
method: "POST",
我滿心歡喜的以為可以了,結果并不可以。。。后臺還是跟我說獲得的數據有問題,結果我 console.log() 了看 給我返回的數據,它竟然還是個 json 。。。說好的 form 呢!感覺受到了欺騙。
瀕臨崩潰。幸好這時候一個老司機點醒了我:為啥那么糾結在本地數據是什么樣子的?歸根結底我們是要把數據傳到后臺去,那么只需要讓數據在請求里面是 form 的格式不就 OK 了?所以 form 表單在請求里面是長什么樣子的呢?
json數據:
{name: "lypeer", gender: "男"}
form數據:
"name=lypeer & gender=男"
所以只要直接對數據進行操作,不用去管什么鬼 json 對象 form 對象什么的,那位老司機寫了個方法,我無恥的直接拿來用了:
function json2Form(json) {
var str = [];
for(var p in json){
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(json[p]));
}
return str.join("&");
}
ok,然后就可以用這個方法轉換數據后來 post 一發:
formSubmit: function (event) {
console.log(event)
wx.request({
url: Constant.BASE_URL + "/add2gank",
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST",
data: Util.json2Form(event.detail.value).concat("&debug=false"),
complete: function (res) {
//省略
}
})
}
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
這里有一點需要注意,必需修改 content-Type 為 application/x-www-form-urlencoded ,不然還是會出問題。
通過上面的方式就可以愉快的給后臺傳表單啦~~~另外關于 這個標簽,雖然說他不會直接給我們返回 form 表單,但是我感覺它還是很好用的,可以直接獲得里面的很多信息,不用很麻煩的一個一個去獲取數據了。不過這個標簽也是有一些坑的,下面會講到它。
7,解析 HTML 代碼塊?
有時候我們會有解析 HTML 代碼塊的需求(爬了一個網頁需要解析,或者后臺出于某種原因返回給你了一個 HTML 代碼塊),但是我們能獲得的通常是一個 String 值( json 里返回的),在這種情況下通常我們會想到兩種解析方式:直接使用正則匹配字符串或者將其裝化成一個 DOM(Document Object Model,文檔對象模型,沒怎么接觸過 JS 的同學可能對這個不太清楚) 然后解析。
直接使用正則的方式這里我就不具體說了,這玩意兒在有些時候還是很好用的,但是在有些時候不那么方便,畢竟它不是為了解析 HTML 而生的。而一提到轉化為 DOM , 大家的腦海里就會浮現出這行代碼來:
var el = document.createElement( 'html' ); el.innerHTML = htmlString;
再然后就可以對 el 執行一系列的解析操作了:
el.getElementById( idName ) el.getElementsByTagName( tagName )......
毫無疑問,這種方式在大多數情況下是比正則來的簡單方便的,畢竟你不需要絞盡腦汁去寫合適的正則表達式了。那么問題來了,在小程序里面我們無法直接獲得 window 和 document 對象,那么如何把一段 HTML 代碼的 String 值轉化為 DOM 呢?不知道那些前端老司機是怎么做的,反正我是這么做的:
function parseHtml(htmlBlock) { var parser = new DOMParser(); return parser.parseFromString(htmlBlock, "text/html");}
我驚訝的發現,雖然微信小程序里面沒有 ducument , window 的概念,但是可以通過 DOMParser 對象來獲得一個 document 對象 ……不要問我怎么發現的,這里面的艱辛不足為外人道也。
然后我們就可以愉快的通過這個返回的對象來進行一系列解析操作啦~~~
在微信小程序的官方文檔里,是指明了 <form/> 標簽里可以提交 <picker/> 的數據的,但是如果你真的在 <form/> 標簽里放了一個 <picker/> 的話,你會發現,童話里都是騙人的。什么鬼!說好的數據呢!!!死活都獲取不了數據,甚至還會讓整個程序崩掉。并且坑爹的是,在小程序官網上面的那個 DEMO 里面,關于 <form/> 標簽的使用有一個例子,例子里面幾乎包含了 <form/> 標簽中會提取數據的所有控件,就是沒有 <picker/> 。
那怎么辦?這當然是難不倒我的。最終我采取了這樣的方式來解決這個問題:
<picker bindchange="onPickerChanged" value="{{index}}" range="{{array}}">
<input class="picker" disabled="disabled" name="type" value="{{array[index]}}"/>
</picker>
這是一個 <form/> 標簽里面的 <picker/> 標簽,我采取的方式是用一個 <input/> 標簽來獲取 <picker/> 的值,然后讓 <form/> 獲取 <input/> 的值,從而達到將 <picker/> 里面的值傳遞給 <form/> 的目的。
9,要實現多層列表?
在做 wechat-weapp-gank 的每天干貨展示的頁面的時候,有一個這樣的頁面需要實現:

這個東西說白了就是個兩層的列表,在原先做 Android 的時候這個是很容易的,直接嵌套嘛,但是現在做小程序的這個效果還是遇到了一些問題。這其中最大的問題就是在嵌套的過程中究竟在綁定數據的時候應該怎么寫——第二個列表應該怎么傳數據進去呢?第二個列表的列表項應該怎么獲取數據呢?最后我摸索出來的結果是這樣的:
<view class="frame" wx:for="{{data}}">
<view class="tag">{{item.tag}}</view>
<view wx:for="{{item.singleItems}}">
<view class="singleItem" href="{{item.src}}">{{index}},{{item.title}}</view>
</view>
</view>
其中 data 是一個數組,它里面裝的是一個一個的的 json 數據,每個 json 數據里面又裝了 tag ,singleItems 等數據,其中 singleItems 又是一個數組,它里面裝的也是一個一個的 json 數據,每個 json 數據里裝了每個二級列表的 item 所需的數據。
具體的可以去我的項目代碼里去看,具體的代碼路徑在這里:post.wxml 和 post.js。
10,如何方便愉快的實現類似 Java 里面的靜態變量的效果?
這點的話純粹是我的一點執念吧,我是從事 Android 開發的,也有點開發中的小癖好,喜歡把一些字符串弄成全局靜態的放到一個專門的地方去。如果是在 Java 里面的話,我喜歡這樣做:

然后在調用的時候就可以這樣做:
String appId = Constants.AppSign.V_APP_ID;
這樣做我覺得很舒服,條理很清晰。但是在微信小程序中想要得到這樣的體驗就很困難——不過還是讓我找到了方法——在小程序里面,是可以通過module.exports 將一個 js 文件模塊化,然后讓別的 js 文件通過 require( URL ) 引用的,我們可以通過這個特性來實現字符串的全局化,像這樣:

這樣的話,我們就可以在需要使用的時候這樣:

這個其實不算踩過的坑哈,只是一個 Android 程序員的小執念而已,大家可以無視。。。
結語
最近在惡補一些前端的東西,感覺我已經快成為一個前端開發工程師了。。。
|