血淚總結:如何從微信小程式的坑跳進支付寶小程式的大坑

蘋果API搬運工發表於2018-08-05

眾所周知,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 事件回撥。

  1. my.getBluetoothAdapterState判斷是否已開啟,已經開啟可正常操作;
  2. 未開啟的話,再呼叫my.openBluetoothAdapter來開啟;
  3. 在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 上widthheight無效!!!!即永遠顯示圖片自身的真實大小!

更開放的 webview

微信中的 webview 元件有很多限制,最常見的是 webview 和小程式的通訊是受限的,雖然有專門的函式,但是官方說傳送的資料只有在頁面銷燬或使用者手動點選分享時,小程式才會真正收到訊息。

還有就是微信小程式中,webview 元件強制全屏且不可被覆蓋。

支付寶中就沒有這麼多限制。

總結

總之,支付寶小程式和微信小程式相似度非常高,熟悉js和vue的同學可以在2周內就熟練將一個小專案從微信小程式轉換成支付寶小程式;

兩者的IDE也都是基於VS Code做的二次開發,介面類似,容易上手,目前支付寶小程式IDE的功能更少一些.

目前,兩者坑不少,而支付寶小程式是比微信小程式更大的坑...

相關文章