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