微信小程序監(jiān)聽(tīng)用戶(hù)登錄事件的實(shí)現(xiàn)方法
最近在開(kāi)發(fā)小程序,小程序既需兼顧針對(duì)新用戶(hù)的內(nèi)容預(yù)覽,又要為注冊(cè)用戶(hù)提供服務(wù),簡(jiǎn)單梳理下,基本需求如下:
- 小程序共三個(gè)tab頁(yè),所有用戶(hù)都可以瀏覽首頁(yè)內(nèi)容,了解我們可以提供的優(yōu)質(zhì)服務(wù);
- 進(jìn)入其他兩個(gè)頁(yè)面之后,如果用戶(hù)沒(méi)有登錄,那就顯示登錄按鈕,如果登錄了,則顯示服務(wù)內(nèi)容;
- 用戶(hù)在一個(gè)頁(yè)面登陸之后,全局生效。
就這么個(gè)看起來(lái)很簡(jiǎn)單的需求,也經(jīng)過(guò)了如下迭代:
- 將登錄狀態(tài)和憑據(jù)存儲(chǔ)在 App.globalData.authorize 中,每個(gè)需要授權(quán)的頁(yè)面 onload 生命周期檢查 App.globalData.authorize.authorized ,為 true 時(shí)渲染服務(wù)內(nèi)容,為 false 則顯示登錄按鈕;
- 但如果打開(kāi)了需要授權(quán)的頁(yè)面 A 但是沒(méi)有登錄,再打開(kāi)頁(yè)面 B 登錄,這時(shí)候回到 A 頁(yè)面,登錄按鈕赫然在眼,這是因?yàn)?A 頁(yè)面的 onload 回調(diào)函數(shù)只執(zhí)行了一次;
- 為了能在 A 頁(yè)面及時(shí)共享 B 頁(yè)面登錄后的狀態(tài),在 A 頁(yè)面的 onshow 生命周期里再獲取了一次登錄狀態(tài),但這樣一來(lái),打開(kāi) A 頁(yè)面的時(shí)候,會(huì)出現(xiàn)短暫的白屏,用戶(hù)甚至有可能看到按鈕變成服務(wù)內(nèi)容的整個(gè)過(guò)程。
翻遍小程序 API 文檔 ,也沒(méi)有發(fā)現(xiàn)用于監(jiān)聽(tīng)登錄的生命周期,就算有也用不了,因?yàn)槲覀冇兄约旱馁~號(hào)體系,服務(wù)端認(rèn)證完畢才算真正的登錄成功。
所以我決定自己包裝原有的 Page 函數(shù),添加一個(gè) onauth 生命周期——
首先是自定義登錄事件的觸發(fā)與監(jiān)聽(tīng),官方的EventChannel 需要向后兼容,橫豎是個(gè)訂閱回調(diào),那我還不如自己擼一個(gè)得了:
/**
* @file utils/event.js
*/
/**
* @const EMPTY_HANDLER
* @desc 空事件回調(diào),被取消事件將被指向此函數(shù)
*/
const EMPTY_HANDLER = () => {};
/**
* @const eventSet - 事件監(jiān)聽(tīng)函數(shù)集
*/
const eventSet = {
authorize: []
};
/**
* @function emit - 發(fā)送全局事件
* @param {String} type - 事件類(lèi)型
* @param {Object} event - 事件對(duì)象
*/
export const emit = (type, event) => (eventSet[type] || []).forEach(item => item(Object.freeze(event)));
/**
* @function on - 注冊(cè)全局事件
* @param {String} type - 事件類(lèi)型
* @param {Function} callback - 事件回調(diào)函數(shù)
*/
export const on = (type, callback) => {
if (!eventSet[type]) {
eventSet[type] = [];
}
if (!callback instanceof Function) {
throw new Error('callback must be a Function!');
}
return eventSet[type].push(callback)
};
/**
* @function off - 取消對(duì)某事件的監(jiān)聽(tīng)
* @param {String} type - 事件類(lèi)型
* @param {Number} id - 需要取消的事件ID,即 registEvent 所返回的值
*/
export const off = (type, id) => {
if (!eventSet[type]) return
eventSet[type][id - 1] = EMPTY_HANDLER
// 如果某類(lèi)事件已經(jīng)全被取消的話(huà),將其置為空數(shù)組
const noListener = !eventSet[type].reduce((pre, cur) => (cur && cur === EMPTY_HANDLER) || pre, false);
if (noListener){
eventSet[type] = []
};
}
然后是對(duì) Page 函數(shù)的魔改:
/**
* @file utils/auth-page.js
*/
import { on } from '/event.js';
export const AuthPage = function(options){
const { onAuth, data, onLoad } = options;
const userInfo = {
nickName: '', // 昵稱(chēng)
account: '', // 賬號(hào)
avatar: { // 頭像
small: '',
middle: '',
large: ''
},
title: 'student', // 頭銜
phoneNumber: 0, // 電話(huà)號(hào)碼
gender: 'secret', // 性別
'class': '' // 班級(jí)
}
if (options.data){
options.data.authorized = false;
options.data.userInfo = userInfo
} else {
options.data = {
authorized: false,
userInfo: userInfo
}
}
/**
* 仍舊調(diào)用原始的 Page 方法
*/
Page(Object.assign(
options,
{
onLoad: function () {
const { authorize, userInfo } = getApp().globalData;
// 執(zhí)行開(kāi)發(fā)者期望的 onload 事件
onLoad instanceof Function && onLoad.bind(this)(arguments);
// 頁(yè)面初始化時(shí),若已經(jīng)授權(quán),直接執(zhí)行授權(quán)回調(diào)
// 否則將授權(quán)回調(diào)注冊(cè)為授權(quán)事件回調(diào)
if (onAuth instanceof Function){
if (authorize.authorized){
onAuth.bind(this)({
type: 'authorize',
authorized: true,
token: authorize.token,
userInfo: userInfo
});
} else {
on('authorize', onAuth.bind(this));
}
}
}
}
));
}
最后,在登錄組件的里:
import { emit } from '../../utils/event.js';
wx.login({
success: res => {
// ...這里省略了一些復(fù)雜的登錄流程
getApp().globalData.authorize = {
authorized: true
};
emit('authorize', res);
}
})
然后,在兩個(gè)需要登錄的 tab 頁(yè)引入 AuthPage 替換原有的 Page 函數(shù),并在配置項(xiàng)里寫(xiě) onAuth 回調(diào),就可以監(jiān)聽(tīng)登錄事件了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 微信小程序局部刷新觸發(fā)整頁(yè)刷新效果的實(shí)現(xiàn)代碼
- 微信小程序 實(shí)現(xiàn)拖拽事件監(jiān)聽(tīng)實(shí)例詳解
- 微信小程序 監(jiān)聽(tīng)手勢(shì)滑動(dòng)切換頁(yè)面實(shí)例詳解
- 微信小程序全局變量改變監(jiān)聽(tīng)的實(shí)現(xiàn)方法
- 微信小程序在其他頁(yè)面監(jiān)聽(tīng)globalData中值的變化
- 微信小程序?qū)崿F(xiàn)watch監(jiān)聽(tīng)
- 微信小程序?qū)崿F(xiàn)頁(yè)面監(jiān)聽(tīng)自定義組件的觸發(fā)事件
相關(guān)文章
javascript FormatNumber函數(shù)實(shí)現(xiàn)方法
如果有一個(gè)數(shù)字498.8573945,如何把它格式化成兩位小數(shù)據(jù)呢?用過(guò)asp的都知道,在vbscript里我們可以調(diào)用formatnumber,即用formatnumber(498.8573945,2)就可以輸出:498.86。2008-12-12
layer.alert自定義關(guān)閉回調(diào)事件的方法
今天小編就為大家分享一篇layer.alert自定義關(guān)閉回調(diào)事件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
JS旋轉(zhuǎn)實(shí)現(xiàn)轉(zhuǎn)盤(pán)抽獎(jiǎng)效果
這篇文章主要為大家詳細(xì)介紹了JS旋轉(zhuǎn)實(shí)現(xiàn)轉(zhuǎn)盤(pán)抽獎(jiǎng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
div浮層,滾動(dòng)條移動(dòng),位置保持不變的4種方法匯總
這篇文章主要是對(duì)div浮層,滾動(dòng)條移動(dòng),位置保持不變的4種方法進(jìn)行了匯總介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-12-12
javascript getElementByTagName的使用
javascript getElementByTagName當(dāng)鼠標(biāo)放上去時(shí)將超鏈接的顏色設(shè)為藍(lán)色的。2009-06-06
JavaScript中isPrototypeOf函數(shù)作用和使用實(shí)例
這篇文章主要介紹了JavaScript中isPrototypeOf函數(shù)作用和使用實(shí)例,本文講解了它的作用和使用方法以及使用實(shí)例,需要的朋友可以參考下2015-06-06
JavaScript實(shí)現(xiàn)跑馬燈抽獎(jiǎng)活動(dòng)實(shí)例代碼解析與優(yōu)化(二)
這篇文章主要介紹了JavaScript實(shí)現(xiàn)跑馬燈抽獎(jiǎng)活動(dòng)實(shí)例代碼解析與優(yōu)化(二)的相關(guān)資料,需要的朋友可以參考下2016-02-02

