微信小程序监听用户登录事件的实现方法
最近在开发小程序,小程序既需兼顾针对新用户的内容预览,又要为注册用户提供服务,简单梳理下,基本需求如下:
- 小程序共三个tab页,所有用户都可以浏览首页内容,了解我们可以提供的优质服务;
- 进入其他两个页面之后,如果用户没有登录,那就显示登录按钮,如果登录了,则显示服务内容;
- 用户在一个页面登陆之后,全局生效。
就这么个看起来很简单的需求,也经过了如下迭代:
- 将登录状态和凭据存储在App.globalData.authorize中,每个需要授权的页面onload生命周期检查App.globalData.authorize.authorized,为true时渲染服务内容,为false则显示登录按钮;
- 但如果打开了需要授权的页面A但是没有登录,再打开页面B登录,这时候回到A页面,登录按钮赫然在眼,这是因为A页面的onload回调函数只执行了一次;
- 为了能在A页面及时共享B页面登录后的状态,在A页面的onshow生命周期里再获取了一次登录状态,但这样一来,打开A页面的时候,会出现短暂的白屏,用户甚至有可能看到按钮变成服务内容的整个过程。
翻遍小程序API文档,也没有发现用于监听登录的生命周期,就算有也用不了,因为我们有着自己的账号体系,服务端认证完毕才算真正的登录成功。
所以我决定自己包装原有的Page函数,添加一个onauth生命周期——
首先是自定义登录事件的触发与监听,官方的EventChannel需要向后兼容,横竖是个订阅回调,那我还不如自己撸一个得了:
/**
*@fileutils/event.js
*/
/**
*@constEMPTY_HANDLER
*@desc空事件回调,被取消事件将被指向此函数
*/
constEMPTY_HANDLER=()=>{};
/**
*@consteventSet-事件监听函数集
*/
consteventSet={
authorize:[]
};
/**
*@functionemit-发送全局事件
*@param{String}type-事件类型
*@param{Object}event-事件对象
*/
exportconstemit=(type,event)=>(eventSet[type]||[]).forEach(item=>item(Object.freeze(event)));
/**
*@functionon-注册全局事件
*@param{String}type-事件类型
*@param{Function}callback-事件回调函数
*/
exportconston=(type,callback)=>{
if(!eventSet[type]){
eventSet[type]=[];
}
if(!callbackinstanceofFunction){
thrownewError('callbackmustbeaFunction!');
}
returneventSet[type].push(callback)
};
/**
*@functionoff-取消对某事件的监听
*@param{String}type-事件类型
*@param{Number}id-需要取消的事件ID,即registEvent所返回的值
*/
exportconstoff=(type,id)=>{
if(!eventSet[type])return
eventSet[type][id-1]=EMPTY_HANDLER
//如果某类事件已经全被取消的话,将其置为空数组
constnoListener=!eventSet[type].reduce((pre,cur)=>(cur&&cur===EMPTY_HANDLER)||pre,false);
if(noListener){
eventSet[type]=[]
};
}
然后是对Page函数的魔改:
/**
*@fileutils/auth-page.js
*/
import{on}from'/event.js';
exportconstAuthPage=function(options){
const{onAuth,data,onLoad}=options;
constuserInfo={
nickName:'',//昵称
account:'',//账号
avatar:{//头像
small:'',
middle:'',
large:''
},
title:'student',//头衔
phoneNumber:0,//电话号码
gender:'secret',//性别
'class':''//班级
}
if(options.data){
options.data.authorized=false;
options.data.userInfo=userInfo
}else{
options.data={
authorized:false,
userInfo:userInfo
}
}
/**
*仍旧调用原始的Page方法
*/
Page(Object.assign(
options,
{
onLoad:function(){
const{authorize,userInfo}=getApp().globalData;
//执行开发者期望的onload事件
onLoadinstanceofFunction&&onLoad.bind(this)(arguments);
//页面初始化时,若已经授权,直接执行授权回调
//否则将授权回调注册为授权事件回调
if(onAuthinstanceofFunction){
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=>{
//...这里省略了一些复杂的登录流程
getApp().globalData.authorize={
authorized:true
};
emit('authorize',res);
}
})
然后,在两个需要登录的tab页引入AuthPage替换原有的Page函数,并在配置项里写onAuth回调,就可以监听登录事件了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。