唱吧小程序登錄授權(quán)頁面開發(fā)
基本的流程不用多說,按部就班即可,就是使用wx.login()可以獲得開發(fā)者服務(wù)器向微信接口服務(wù)器請求獲得sessionkey等數(shù)據(jù)時所需要的參數(shù)code,開發(fā)者服務(wù)器以code+appid+appsecret換取用戶唯一標(biāo)識openid和會話密鑰sessionkey。但每一次調(diào)用wx.login()都會更新微信接口服務(wù)器上的session_key。
同樣,改造微信api先,
-
// wechat 登錄封裝
-
const login = () => {
-
return new Promise((resolve, reject) => {
-
wx.login({ success: resolve, fail: reject })
-
})
-
}
而后,在做自己的登錄封裝時,可以先去請求微信的code,然后用在自己的請求中,獲取并存儲自己的登錄態(tài)。
-
let we_login = await wechat.login() // 微信登錄
-
let cb_login = await requestAPI('xxxx/checkCode', { data: {code: we_login.code}})
-
if (cb_login && cb_login.code === 1) {
-
// xxxx 業(yè)務(wù)邏輯
-
} catch (error) {
-
wx.showModal({
-
title: '登錄提示',
-
content: '登錄失敗',
-
showCancel: false
-
})
-
}
而在完成上面整套業(yè)務(wù)邏輯過程中,可能會遇到一些意想不到的坑,這里面我印象比較深刻的有兩個,第一個是關(guān)于授權(quán)的問題,另一個就是關(guān)于小程序生命周期與頁面生命周期初始化過程中異步請求回調(diào)順序的問題。
-
授權(quán)問題
先說第一個問題,關(guān)于授權(quán)框喚起的問題,只有用戶授權(quán)后,才可以進(jìn)一步獲取用戶的信息,這個框在最初是可以通過wx.getUserinfo()方法直接喚起,而在5月份以后,微信去掉了這個方法的功能,只能通過固定的button open-type去引導(dǎo)用戶授權(quán)。
所以在底層邏輯的設(shè)計過程中,就要拋棄之前l(fā)ogin之后獲取用戶授權(quán)信息的設(shè)計思路,而是進(jìn)行拆分,將login和授權(quán)的邏輯分開。
在必須要授權(quán)操作的地方例如我們小程序中需要“參賽”或者“關(guān)注”的地方,進(jìn)行單獨授權(quán)的處理,通過使用wx.getSetting獲取用戶的授權(quán)情況 1) 如果用戶已經(jīng)授權(quán),直接調(diào)用wx.getUserInfo獲取用戶最新的信息 2) 用戶未授權(quán),在界面中顯示一個按鈕提示用戶登入,當(dāng)用戶點擊并授權(quán)后就獲取到用戶的最新信息。
-
onLaunch和onLoad異步回調(diào)順序問題
這個問題簡單來說,就是小程序啟動有自己的生命周期onLaunch->onShow->onHide,而每個page的實例化也有自己的生命周期,onLoad->onShow->onReady->onHide->onUnload
然而在開發(fā)過程中,會遇到這種情況,在App啟動onLaunch的時候,發(fā)起登錄請求,并注冊到我們自己的服務(wù)器上以便使用,這個過程中,
app on launch -> request -> success -> page onload
是無法判斷success和page onload哪個先,會導(dǎo)致頁面初始化數(shù)據(jù)失敗的情況,為了解決這個問題,我們團(tuán)隊也是想到了幾種常見的解決方案。
解決方案一 就是在request success中處理,使用getCurrentPages方法獲取是否頁面先于success生成,如果生成我們就強(qiáng)制讓頁面再次渲染。
這顯然是一種hack的方式, 在實際使用過程當(dāng)中,如果登錄邏輯比較復(fù)雜,這個方法不是十分便利,page onload在一些特殊情況也會被調(diào)用,這顯然不是我們想看到的
-
if (getCurrentPages().length != 0) {
-
getCurrentPages()[getCurrentPages().length - 1].onLoad()
-
}
解決方案二(目前我在開發(fā)中使用的是這種方案)
在login的邏輯里,增加一個回調(diào)函數(shù)cbLoginCallBack。
Page頁面判斷一下當(dāng)前app.globalData.sessionKey是否存在,如果沒有(第一次)則定義定義一個app方法(回調(diào)函數(shù))
-
// Login Request
-
if (app.cbLoginCallBack) {
-
typeof app.cbLoginCallBack == 'function' && app.cbLoginCallBack(cb_login.data)
-
}
-
// 邏輯頁面
-
if (app.globalData.sessionkey) {
-
// init data
-
} else {
-
app.cbLoginCallBack = res => {
-
if (res) {
-
// init data
-
}
-
} }
App頁面在請求success后判斷時候有Page頁面定義的回調(diào)方法,如果有就執(zhí)行該方法。因為回調(diào)函數(shù)是在Page里面定義的所以方法作用域this是指向Page頁面。