JavaScript

超轻量级php框架startmvc

微信小程序监听用户登录事件的实现方法

更新时间:2020-09-22 10:30:01 作者:startmvc
最近在开发小程序,小程序既需兼顾针对新用户的内容预览,又要为注册用户提供服务,简

最近在开发小程序,小程序既需兼顾针对新用户的内容预览,又要为注册用户提供服务,简单梳理下,基本需求如下:

  • 小程序共三个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 需要向后兼容,横竖是个订阅回调,那我还不如自己撸一个得了:


/**
 * @file utils/event.js
 */

/**
 * @const EMPTY_HANDLER
 * @desc 空事件回调,被取消事件将被指向此函数
 */
const EMPTY_HANDLER = () => {};

/**
 * @const eventSet - 事件监听函数集
 */
const eventSet = {
 authorize: []
};

/**
 * @function emit - 发送全局事件
 * @param {String} type - 事件类型
 * @param {Object} event - 事件对象
 */
export const emit = (type, event) => (eventSet[type] || []).forEach(item => item(Object.freeze(event)));

/**
 * @function on - 注册全局事件
 * @param {String} type - 事件类型
 * @param {Function} callback - 事件回调函数
 */
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 - 取消对某事件的监听
 * @param {String} type - 事件类型 
 * @param {Number} id - 需要取消的事件ID,即 registEvent 所返回的值
 */
export const off = (type, id) => {
 if (!eventSet[type]) return

 eventSet[type][id - 1] = EMPTY_HANDLER

 // 如果某类事件已经全被取消的话,将其置为空数组
 const noListener = !eventSet[type].reduce((pre, cur) => (cur && cur === EMPTY_HANDLER) || pre, false);
 if (noListener){
 eventSet[type] = []
 };
}

然后是对 Page 函数的魔改:


/**
 * @file utils/auth-page.js
 */

import { on } from '/event.js';

export const AuthPage = function(options){
 const { onAuth, data, onLoad } = options;
 const userInfo = {
 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 事件
 onLoad instanceof Function && onLoad.bind(this)(arguments);

 // 页面初始化时,若已经授权,直接执行授权回调
 // 否则将授权回调注册为授权事件回调
 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 => {
 // ...这里省略了一些复杂的登录流程
 getApp().globalData.authorize = {
 authorized: true
 };
 emit('authorize', res);
 }
})

然后,在两个需要登录的 tab 页引入 AuthPage 替换原有的 Page 函数,并在配置项里写 onAuth 回调,就可以监听登录事件了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

小程序监听登录 小程序监听用户 小程序监听