眾所周知,iOS沒人要了,小程式現在火了...
哈哈,開玩笑,不過小程式真是非常火所以,今天我就來講講最近折騰出的小程式總結:如何從微信小程式的坑跳進支付寶小程式的大坑!
小程式非常適合不經常使用的線下服務場合,比如偶爾在某飯店點個菜,偶爾在某景區租個車,等等
如果你已經有了微信小程式,那麼再開發一個支付寶小程式也並沒有多難.畢竟80%以上的程式碼是通用的.最大的困難可能還是對小程式語法/api的不熟悉,還有文件不夠全面.
於是我最近就經歷了這樣一系列填坑操作.
小程式API差異:
xml
對於xml來說,最大的不同除了檔案字尾名不同外,其實就是wx:改為了a:,還有事件繫結由bind開頭改為用on開頭:
微信 | 支付寶 | 備註 |
---|---|---|
檔名.wxml | 檔名.axml | 字尾名不同 |
wx:if | a:if | |
wx:elif | a:elif | |
wx:else | a:else | |
wx:for-item | a:for-item | |
wx:key | a:key | |
bindtap | onTap | |
bindsubmit | onSubmit | form元件 |
bindreset | onReset | form元件 |
bindinput | onIpput | input元件 |
bindchange | onChange | switch元件 |
bindmarkertap | onMarkerTap | map元件 |
bindcontroltap | onControlTap | map元件 |
css
css中兩者幾乎一模一樣,基本不用改動,主要問題在map元件
微信 | 支付寶 | 備註 |
---|---|---|
檔名.wxss | 檔名.acss | 字尾名不同 |
90% | 90vh!important | map元件 |
// 地圖高度設定不能用標籤選擇器:#map
map {
height: 90vh!important;
}
複製程式碼
用其它方法來設定map元件的高度是不起作用的,必須加上!important
;
-
如果還不起作用,請務必使用
90vh!important
這樣; -
如果還不起作用,請注意不要使用標籤選擇器:
#map
-
如果還有問題,請在xml中調整一下,在所有元件最外層包上一個
<view>
元件,並將其設定為100%寬高; -
別問我怎麼知道的,我搞了好幾天....
還有一點需要注意,相信大家也很容易看出來:
支付寶中view元件佈局預設是包裹內部元件;
也就是說如果view元件內部一個button,button寬高為40rpx,那麼view不會全屏顯示,需要手動設定view元件width:100%;height:100%
js
js的檔案字尾名是相同的,喜大普奔!
最大改變是將wx.改為了my.
微信 | 支付寶 | 備註 |
---|---|---|
wx.showModal | my.confirm | |
wx.getStorageSync('user') | my.getStorageSync({ key: 'user' }).data | 非常蛋疼! |
wx.setStorageSync('area', res.data) | my.setStorageSync({key: 'area', data:res.data}) | 非常蛋疼! |
wx.removeStorageSync('area') | my.removeStorageSync({key:'area'}) | 非常蛋疼! |
wx.request | my.httpRequest | 注意引數header—>headers,結果中的res.statusCode-->res.status |
wx.requestPayment | my.tradePay | 支付介面引數不同:支付寶為拼接的引數,微信為單獨引數;回撥結果支付寶有三種狀態:成功,失敗,未知或支付中;微信只有成功,失敗 |
wx.getSetting | 無 | 許可權在對應api中獲取 |
wx.login | my.getAuthCode | 多了引數scopes: 'auth_user', // 主動授權(彈框):auth_user,靜默授權(不彈框):auth_base |
wx.setNavigationBarTitle | my.setNavigationBar | 不僅能設定title,還能設定背景色等 |
wx.createBLEConnection | my.connectBLEDevice | 藍芽 |
wx.closeBLEConnection | my.disconnectBLEDevice | 藍芽 |
wx.getSystemInfoSync().SDKVersion | my.SDKVersion | |
wx.getSystemInfoSync().system | my.getSystemInfoSync().platform | 注意大小寫:系統平臺android/iOS—>系統平臺Android/iOS;另外個別安卓機型上可能為空!!!!! |
wx.createMapContext('map').includePoints({points: that.data.map.polyline[0].points}) | that.data.map.includePoints = that.getPolyLine(data.border1).points | 改為先在axml中繫結屬性,再設定 |
wx.openLocation() | my.openLocation() | 引數數量不同,型別不同 |
地圖元件中又出現了小麻煩,微信中是拿到mapContext直接設定包含的點,而支付寶中需要先在axml中繫結
<map include-points='{{map.includePoints}}'></map>
複製程式碼
然後改變對應的值並that.setData賦值重新整理介面.
還有開啟內建地圖導航的API,也有差異:微信中只需要三個引數:經度,緯度,名稱.經緯度為Number型別.而支付寶中需要四個引數:經度,緯度,名稱,地址.經緯度為String型別
json
json的檔案字尾名也是相同的,喜大普奔!
微信 | 支付寶 | 備註 |
---|---|---|
navigationBarTitleText | defaultTitle | 標題 |
navigationBarBackgroundColor | titleBarColor |
更大的坑
藍芽介面卡
更大的坑還是出在了藍芽元件上,微信中多次呼叫開啟藍芽介面卡沒有問題,但支付寶小程式中,藍芽已經連線的情況下再重複呼叫就導致連線失敗或斷開重連:
wx.openBluetoothAdapter()—>my.openBluetoothAdapter()
複製程式碼
所以建議先判斷介面卡的狀態,在error回撥中,根據err.code判斷發現沒有開啟時再開啟藍芽介面卡.
如果沒有提前開啟Adapter,那麼後面的my.onBluetoothAdapterStateChange
監聽是無法工作的.
官方文件:初始化小程式藍芽模組,生效週期為呼叫 my.openBluetoothAdapter 至呼叫 my.closeBluetoothAdapter 或小程式被銷燬為止。 在小程式藍芽介面卡模組生效期間,開發者可以正常呼叫下面的小程式API,並會收到藍芽模組相關的 on 事件回撥。
- 用
my.getBluetoothAdapterState
判斷是否已開啟,已經開啟可正常操作; - 未開啟的話,再呼叫
my.openBluetoothAdapter
來開啟; - 在complete回撥中,再呼叫
my.getBluetoothAdapterState
判斷是否已開啟,並設定監聽;
藍芽搜尋新裝置
接下來,是在搜尋藍芽的回撥裡,藍芽廣播中的advertisData格式不同,支付寶中是16進位制的字串,而微信中是ArrayBuffer,也就是二進位制陣列.
微信官方文件也做了說明:advertisData為當前藍芽裝置的廣播資料段中的ManufacturerData資料段 (注意:vConsole 無法列印出 ArrayBuffer 型別資料)
my.onBluetoothDeviceFound(function (res) {
let devices = res.devices // 裝置列表
for (let i in devices) {
//支付寶中,將16進位制字串轉換為真正的字串
let mac = hexToString(devices[i].advertisData).toLowerCase()
//微信中,將二進位制陣列轉換為字串
//let mac = ab2str(devices[i].advertisData).toLowerCase()
let deviceId = devices[i].deviceId
}
}
複製程式碼
獲取已連線的藍芽裝置
還有一個不同,獲取處於已連線狀態的藍芽裝置列表.
微信中只要傳入service陣列就可以準確獲取到對應的藍芽裝置,並在success中給出裝置的資訊;
而支付寶中必須傳入廣播中公開的serviceId才能找到對應的裝置,success回撥中給出的也是裝置的廣播資料...
舉個例子:一個藍芽裝置:小米手環2s,共有4個service:['AAAA','BBBB','CCCC','DDDD'],其中AAAA和BBBB是公開的,也就是放在廣播中的,無須連線就可以獲取到;而CCCC和DDDD是必須連線上之後才能獲取到的.
在微信中,傳入CCCC和DDDD,就可以得到當前已經連線中的'小米手環2s'(可能有多個,所以是陣列);
而在支付寶中,傳入CCCC和DDDD得到的是空陣列.必須傳入AAAA或BBBB這種公開在廣播中的serviceId才能找到已連線的所有'小米手環2s':
my.getConnectedBluetoothDevices({ // 獲取處於已連線狀態的裝置
//services: [that.data.u1], that.data.u2],//支付寶中有限制
success: function (res) {
res.devices.forEach(function (ud, index) {
if (ud.deviceId === that.data.deviceId) {//目標裝置
console.log('目標裝置已連線',ud.deviceId,that.data.deviceId)
}
})
}
}
複製程式碼
藍芽寫入操作
微信中寫入的value是ArrayBuffer即二進位制,而支付寶中是Hex String即16進位制字串.
比較坑的是官方說明:
value: Hex String 必填 藍芽裝置特徵值對應的值,16進位制字串,限制在20位元組內
這個20位元組,實際指的是二進位制資料的長度,而16進位制的2位才代表1位元組,所以每次傳入的字串長度應該是:小於40!!!!
my.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: value,
success: function (res) {
console.log('向藍芽寫入資料 success', res)
},
fail: function (res) {
console.log('向藍芽寫入資料失敗', res)
}
})
複製程式碼
藍芽狀態監聽
還有一個比較搞笑的是,支付寶小程式官方文件中對藍芽各種監聽的說明:
// 開始監聽藍芽變化,先移除一下
my.offBluetoothAdapterStateChange();//tip: 為防止多次註冊事件監聽導致一次事件多次回撥,建議每次呼叫on方法監聽事件之前,先呼叫off方法,關閉之前的事件監聽。
my.onBluetoothAdapterStateChange(function (res) {/*監聽到介面卡狀態改變*/})
複製程式碼
所有的監聽事件api都加了說明,讓先呼叫off方法移除一下,以防重複監聽,這種操作讓我這個做過iOS原生藍芽開發的非常不適應,簡直哭笑不得呀.
再看微信的小程式,根本就沒有off方法,估計是內部做了防止重複監聽的處理.
在安卓上列印為空
4月份已經有人在官方論壇上反應onBluetoothDeviceFound返回值列印為空了,官方回應Demo是正常的.我也遇到了這個問題.
還有人說是開啟除錯開關導致的異常,但我關掉除錯介面,也沒有用.....
經過與官方Demo的仔細對比,發現最大問題是裡面有資料,但在安卓上列印不出來...
my.onBluetoothDeviceFound(function (res) {
let devices = res.devices // 裝置列表
console.log('onBluetoothDeviceFound', res)//列印出的res在安卓上為空
console.log(res)//列印出的res在安卓上為[object Object]
console.log(JSON.stringify(res))//在安卓上終於成功輸出了...
})
複製程式碼
後來仔細一測試,安卓上,所有的東西都不能直接列印,官方示例中全都是用JSON.stringify(res)
來列印輸出的.而正常取值是不受影響的.
蛋碎一地呀~!!!
switch-case的坑
在支付寶小程式中,一個簡單的switch-case語法竟然出錯了!!!
switch (code) {
case 0:
console.log('0')
break;
case 1:
console.log('1')
break;
case 2:
console.log('2')
break;
default:
console.log('default')
複製程式碼
出錯原因是,當code=0時,case 0
分支無法進入,直接進入了default
分支,真是無比蛋疼!!!
其他分支沒有問題,避免方法是,不使用case 0
,改成case 10
~
安卓上刪除小程式不會清理資料
在微信上,如果使用者刪除了小程式,所有產生的/儲存的資料都會被清理掉。
在支付寶上,iOS 表現和微信一致,都會被刪除;而安卓上setStorageSync
儲存的資料不會被刪除!!!!!
my.setStorageSync({ key: 'user', data: userData })
複製程式碼
所以必須手動判斷刪除:
my.removeStorageSync({ key: 'user' })
複製程式碼
真是讓人無比蛋疼!!坑爹啊!!!
地圖元件 control 控制元件的圖示
由於現在支付寶地圖元件層級最高,還沒有推出cover-image
功能,所以要在地圖上覆蓋按鈕,就只能用control
元件。這樣需要給control
元件設定iconPath
,如下:
controls: [{
id: 10,
iconPath: imgPath + "icon_new_user.png",
position: {
left: 280,
top: 400,
width: 35,
height: 35
},
clickable: true
}]
複製程式碼
這裡有個坑,就是position
在安卓上正常的,在 iOS 上width
和height
無效!!!!即永遠顯示圖片自身的真實大小!
更開放的 webview
微信中的 webview 元件有很多限制,最常見的是 webview 和小程式的通訊是受限的,雖然有專門的函式,但是官方說傳送的資料只有在頁面銷燬或使用者手動點選分享時,小程式才會真正收到訊息。
還有就是微信小程式中,webview 元件強制全屏且不可被覆蓋。
支付寶中就沒有這麼多限制。
總結
總之,支付寶小程式和微信小程式相似度非常高,熟悉js和vue的同學可以在2周內就熟練將一個小專案從微信小程式轉換成支付寶小程式;
兩者的IDE也都是基於VS Code做的二次開發,介面類似,容易上手,目前支付寶小程式IDE的功能更少一些.
目前,兩者坑不少,而支付寶小程式是比微信小程式更大的坑...