首先要聲明的是,我是一名 androids 開發者,之前基本沒有前端開發經驗,甚至連 JS ,HTML 都是為(wei) 了開發小程序現學的一些皮毛——所以文章中所提到的一些點也許在資深前端開發者看來隻是小case,但是站在一個(ge) androids 開發者的角度來看確實是大坑。
前麵就不說太多東(dong) 西了,文章的末尾再談談我對小程序的一些看法——這篇文章主要是談談在開發小程序的過程中遇到的一些坑。
PS:推薦一下我寫(xie) 的一個(ge) 微信小程序版的Gank客戶端:wechat-weapp-gank
最近在一些地方看到很多人在入小程序坑的第一步就出現了很多的問題,其實很早之前(22號)關(guan) 於(yu) 怎樣搞定小程序的開發工具就已經有比較好的資料了,大家可以直接去看一下然後照著做,基本上就沒啥問題:獲取小程序開發工具並正確安裝的教程
目前來講,我們(men) 隻能在微信的開發工具上編譯小程序的代碼,但是這並不意味著我們(men) 必須要在那個(ge) 開發工具上寫(xie) 小程序的代碼——用過那個(ge) 開發工具的人就會(hui) 知道,那個(ge) 開發工具並沒有多好用,代碼提示挺弱雞的,而且沒有自動保存是硬傷(shang) 。
那麽(me) 怎麽(me) 辦呢?我們(men) 完全可以在別的工具裏麵寫(xie) 代碼然後在小程序的開發工具裏麵編譯。我試過 sublime 和 webstorm , 都是可以在上麵開發的,但是最後還是發現 ws 更好用。我就不講 sublime 怎麽(me) 用了,大家隻需要直接在裏麵打開項目文件夾然後點右下角選擇當前的語言就可以了。接下來著重講一講如何在 ws 裏麵編寫(xie) 小程序代碼。
首先選擇小程序的目錄在 ws 裏麵打開,這是很簡單的。但是這個(ge) 時候打開裏麵的文件之後你會(hui) 發現,除了 js 代碼它能認出來之外,其他的代碼他都並不能夠認出來——主要是 .wxml 和 .wxss 文件。為(wei) 什麽(me) 呢?因為(wei) 雖然 .wxml 和 .html 文件很像,.wxss 文件和 .css 文件很像,但是編譯器並不知道!這樣一來,我們(men) 就無法在這兩(liang) 種文件裏麵享受 ws 強大的代碼提示功能了——我們(men) 能接受這種事麽(me) ?果斷不能!那麽(me) 接下來我們(men) 應該怎麽(me) 辦呢?告訴編譯器,.wxml 格式的其實是 HTML 文件,.wxss 格式的其實是 CSS 文件。
上圖把做這件事的流程講的很詳細了,.wxss 文件的轉化同理。這樣做了之後,編輯器就會(hui) 知道他們(men) 的真實麵目,然後就可以有棒棒的代碼提示了(但是請注意,有寫(xie) 微信自己寫(xie) 的東(dong) 西編輯器不僅(jin) 沒有代碼提示反而會(hui) 報錯,不管他就好了)!接下來就可以直接 ws 一個(ge) 桌麵小程序開發工具一個(ge) 桌麵,在 ws 裏麵寫(xie) 了代碼直接劃過去點編譯了。
小程序給我們(men) 開放了很好的接口來進行頁麵之間的跳轉:
但是在這個(ge) 地方微信官方對於(yu) 這一個(ge) 接口並沒有太多的描述,隻是簡簡單單的給了我們(men) 一行代碼:wx.navigateTo({url: "test ? id = 1"});
,其實這裏這樣寫(xie) 是有些難以理解的——test
是個(ge) 什麽(me) 鬼 ? id
是個(ge) 什麽(me) 鬼?中間那個(ge) 問號是個(ge) 什麽(me) 鬼?這都是些什麽(me) 鬼?
反正我看到的時候是一頭霧水的。不過還好,經過一些摸索,終於(yu) 知道了他們(men) 是啥。首先,代碼裏的 test
代表要跳轉到的 page 的url 地址。比如:
那麽(me) 代碼就應該是:
wx.navigateTo({url: "/pages/specific/specific"});
聰明的人可能已經發現了,上麵的代碼沒有了示例代碼裏麵 ? id = 1
的部分,怎麽(me) 回事,是我寫(xie) 錯了麽(me) ?並不是。這一部分其實是跳轉 page 時用來傳(chuan) 值的關(guan) 鍵方法,並不必需,但很有用。
* ?
是一個(ge) 分隔符一樣的東(dong) 西,它的後麵就是所有要傳(chuan) 到目標 page 的值。而這些值是通過鍵值對來一一對應的,每個(ge) 鍵值對之間用 &
隔開。但是要注意的是,似乎這種方式傳(chuan) 值隻能傳(chuan) String 過去,不是 String 類型的值傳(chuan) 過去之後也會(hui) 被轉化為(wei) String 。*比如,我傳(chuan) 了個(ge) array
和 json
過去:
var arrayData = ["firstData" , "secondData"];
var jsonData = {first: "firstData" , second: "secondData"};
wx.navigateTo({url: "/pages/specific/specific ? data: " + arrayData + "&json=" + jsonData});
結果目標page裏接受到的是:
//目標page的onLoad方法
onLoad: function (options) {
//結果是:firstData , secondData
console.log(options.data);
//結果是:f
console.log(options.data[0]);
//結果是:[object Object]
console.log(options.json);
//結果是:undefined
console.log(options.data.first); //很顯然,被轉化了
}
上麵其實也演示了如何在目標 page 裏麵接收傳(chuan) 過來的數據,直接在 onLoad()
裏麵的 options
取就可以了。
另外,其實更多的時候我們(men) 的需求並不是直接傳(chuan) 一個(ge) 固定的參數到目標 page 裏麵去,而是根據用戶的一些操作傳(chuan) 遞不同的值到目標 page 裏麵去,這個(ge) 時候該怎麽(me) 辦呢?要知道,我們(men) 是沒有辦法獲得組件的(這點太坑了,沒有 window 和 document)。這個(ge) 時候,我們(men) 可以通過 dataset 來通過綁定組件數據達到目的。什麽(me) ?你不知道 dataset 是什麽(me) 東(dong) 西?
多讀書(shu) ,多看報,多看文檔少睡覺。
這個(ge) 坑真的是深坑,可能很久很久都不會(hui) 遇到,但是一旦遇到真的很蛋疼。
我拿來練手的項目是 Gank.io 的客戶端,而 Gank 網站上的圖片都是寄放在新浪圖床上的,默認的存儲(chu) 的 url 是https://ww{1 || 2 || 3 || 4}.xxxxx.xxxxx.jpg
,然後在小程序裏死活都加載不出來這些圖片!!!
我一開始不知道到底是小程序的 <image>
標簽的問題還是圖片的問題,就找了很多地方的圖片來做測試,包括 CSDN 上的,簡書(shu) 上的,github 圖床上的,結果是這些圖片都可以正常顯示——甚至新浪微博上的,一些人的頭像,都可以顯示!後來我發現,隻要 URL 是 ww+數字 開頭的圖片,都不能正常的顯示!這也太坑了。。。後來我就在思考怎麽(me) 解決(jue) 這個(ge) 問題——要麽(me) 改變 標簽,他自身肯定是有問題的,可能對某些來源的圖片不太友好;要麽(me) 改變圖片,讓它去適應這個(ge) 標簽。這兩(liang) 方麵要改其實都挺難的,但是顯然第一種方式基本上是不可能的,就隻能在第二種方式上去下功夫。
最後經過不斷地嚐試,我總結了很多規律,最後通過把圖片的 URL 由 ww+數字變成 ws+數字 解決(jue) 了這個(ge) 問題,讓圖片得以顯示在小程序上。比如:
本來的URL:
http://ww1.sinaimg.cn/large/610dc034jw1f87z2n2taej20u011h11h.jpg
變換之後的URL:
http://ws1.sinaimg.cn/large/610dc034jw1f87z2n2taej20u011h11h.jpg
不要問我為(wei) 什麽(me) 這樣改了就可以顯示了,因為(wei) 我也不知道。。。太神奇了。。。
首先想要說的是,作為(wei) 一個(ge) androids 開發者,我非常不適應小程序的數據與(yu) 控件綁定的方式。在 androids 開發的時候,我們(men) 是可以直接獲得控件然後對控件做數據綁定的工作的,而在小程序裏,我並不能夠直接獲得控件的對象,所有的數據綁定與(yu) 動態修改隻能通過維護 Page 裏麵的 data{} 以及調用setData() 方法來進行,我不好評判這兩(liang) 種方式的優(you) 劣,隻能說真的很不習(xi) 慣。
但是有些和我一樣以前沒怎麽(me) 接觸過前端開發的朋友在做這個(ge) 的時候就有可能會(hui) 踩坑了——setData() 是 Page 這個(ge) 層級上的方法,並不是在任何地方調用 this.setData() 方法都可以順利的得到我們(men) 預期的結果的。比方說:
Page({
onLoad: function (options) {
wx.request({
url: Constant.GET_URL,
success: function (res) {
this.setData({...});
}
});
},
});
我在 wx.request()
的回調接口裏麵 success()
裏麵寫(xie) this.setData({...})
,就不能完成預期操作,程序會(hui) 報錯說沒有 setData()
這個(ge) 方法,因為(wei) 這個(ge) 時候 this
獲取到的已經並不是 Page 了,上下文已經發生了變化,那麽(me) 當前層級沒有 setData()
方法就很正常了。那麽(me) 怎麽(me) 解決(jue) 這個(ge) 問題呢?像這樣:
Page({
onLoad: function (options) {
that = this;
wx.request({
url: Constant.GET_URL,
success: function (res) {
that.setData({...})
}
});
},
});var that;
和一開始的區別在於(yu) 多了一個(ge) 全局變量 that
,並且在 onLoad() 方法裏麵對它進行了賦值,使它等於(yu) this
。這樣的話,我們(men) 就可以在這個(ge) Page 的任何地方調用 that.setData()
來動態的改變控件的屬性了。
本來是還有一些問題要談一談的,但是寫(xie) 到這裏篇幅已經挺長的了,就幹脆把其他的放到下一篇裏麵算了。剩下的問題還有:
<form>
標簽獲得的數據也不是。<form/>
裏麵無法獲取 <picker/>
的取值?明明文檔裏有說在 <form/>
裏麵是可以支持 <picker/>
的,結果你會發現死活無法獲得他的值。接下來我想談一下我對小程序的看法。
多謝各位看官看到這,順便去點個(ge) star吧:wechat-weapp-gank