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


Posted in Javascript onNovember 11, 2019

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

  • 小程序共三个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 回调,就可以监听登录事件了。

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

Javascript 相关文章推荐
一个简单的jQuery插件制作 学习过程及实例
Apr 25 Javascript
使用隐藏的new来创建对象
Mar 29 Javascript
jquery 查找select ,并触发事件的实现代码
Mar 30 Javascript
jquerymobile checkbox及时刷新才能获取其准确值
Apr 14 Javascript
基于JS组件实现拖动滑块验证功能(代码分享)
Nov 18 Javascript
利用jquery实现下拉框的禁用与启用
Dec 07 Javascript
jQuey将序列化对象在前台显示地实现代码(方法总结)
Dec 13 Javascript
JavaScript中Require调用js的实例分享
Oct 27 Javascript
解决vue中虚拟dom,无法实时更新的问题
Sep 15 Javascript
总结4个方面优化Vue项目
Feb 11 Javascript
利用vue重构有赞商城的思路以及总结整理
Feb 21 Javascript
ant-design-vue中tree增删改的操作方法
Nov 03 Javascript
javascript 高级语法之继承的基本使用方法示例
Nov 11 #Javascript
JS 遍历 json 和 JQuery 遍历json操作完整示例
Nov 11 #jQuery
javascript/jquery实现点击触发事件的方法分析
Nov 11 #jQuery
jquery ajax 请求小技巧实例分析
Nov 11 #jQuery
javascript 对象 与 prototype 原型用法实例分析
Nov 11 #Javascript
javascript json对象小技巧之键名作为变量用法分析
Nov 11 #Javascript
Vue.js watch监视属性知识点总结
Nov 11 #Javascript
You might like
SONY ICF-SW07收音机电路分析
2021/03/02 无线电
PHP 5.0对象模型深度探索之绑定
2006/09/05 PHP
Php获取金书网的书名的实现代码
2010/06/11 PHP
php+mysqli批量查询多张表数据的方法
2015/01/29 PHP
Laravel 不同生产环境服务器的判断实践
2019/10/15 PHP
jscript之Open an Excel Spreadsheet
2007/06/13 Javascript
Javascript 日期处理之时区问题
2009/10/08 Javascript
PHP abstract与interface之间的区别
2013/11/11 Javascript
JavaScript 常见安全漏洞和自动化检测技术
2015/08/21 Javascript
AngularJS控制器继承自另一控制器
2016/05/09 Javascript
js放到head中失效的原因与解决方法
2017/03/07 Javascript
微信小程序实现点击按钮修改view标签背景颜色功能示例【附demo源码下载】
2017/12/06 Javascript
动手写一个angular版本的Message组件的方法
2017/12/16 Javascript
vue实现跨域的方法分析
2019/05/21 Javascript
Vue动态修改网页标题的方法及遇到问题
2019/06/09 Javascript
JavaScript canvas实现雪花随机动态飘落
2020/02/08 Javascript
vue $router和$route的区别详解
2020/12/02 Vue.js
原生JS实现音乐播放器的示例代码
2021/02/25 Javascript
Python中方法链的使用方法
2016/02/23 Python
对numpy中数组元素的统一赋值实例
2018/04/04 Python
Python实现去除列表中重复元素的方法小结【4种方法】
2018/04/27 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
Django实现分页显示效果
2019/10/31 Python
Python接口测试get请求过程详解
2020/02/28 Python
Python实现动态循环输出文字功能
2020/05/07 Python
雅诗兰黛澳大利亚官网:Estée Lauder澳大利亚
2019/05/31 全球购物
美国孩之宝玩具官网:Hasbro Pulse
2019/06/24 全球购物
在数据文件自动增长时,自动增长是否会阻塞对文件的更新
2014/05/01 面试题
理工学院学生自我鉴定
2014/02/23 职场文书
医院竞聘演讲稿
2014/05/16 职场文书
关于爱国的标语
2014/06/24 职场文书
公司门卫工作职责
2014/06/28 职场文书
毕业证丢失证明范本
2014/09/20 职场文书
大学生村官个人对照检查材料(群众路线)
2014/09/26 职场文书
三年级学生期末评语
2014/12/26 职场文书
使用Redis实现点赞取消点赞的详细代码
2022/03/20 Redis