微信小程序之页面拦截器的示例代码


Posted in Javascript onSeptember 07, 2017

场景

  • 小程序有52个页面,其中13个页面无需任何身份,另外39个页面需要系统角色。对于这39个页面,如果微信用户没有系统角色,则跳转到登录页。
  • 是否有系统角色信息需要通过异步请求来获取。

需求分析&实现

对需求进行抽象,其实要的就是一个过滤器,对小程序页面的访问进行过滤,符合条件的通过,不符合条件进行其他处理。

使用过php的laravel框架的童鞋,肯定一下子就联想到了laravel框架的http中间件:

HTTP 中间件提供一个方便的机制来过滤进入应用程序的 HTTP 请求,例如,Laravel 默认包含了一个中间件来检验用户身份验证,如果用户没有经过身份验证,中间件会将用户导向登录页面,然而,如果用户通过身份验证,中间件将会允许这个请求进一步继续前进。当然,除了身份验证之外,中间件也可以被用来执行各式各样的任务,CORS 中间件负责替所有即将离开程序的响应加入适当的响应头,一个日志中间件可以记录所有传入应用程序的请求。

令人忧桑的是,微信小程序并没有提供针对Page实例的中间件机制。所以只能从Page实例的生命周期处下手。

微信小程序之页面拦截器的示例代码

对于onLoad,一个页面只会调用一次;对于onShow,每次打开页面(比如小程序从后台转到前台)都会调用一次。

在onLoad或者onShow钩子函数里,对用户身份进行校验,通过后则拉取该页面需要的数据,否则跳转到登录页。

//orderDetail.js
onShow: function () {
  let that = this;
  //身份校验
  service.identityCheck(() => {
     //跳转到登录页
     wx.redirectTo({
      url: "/pages/common/login/login"
     });
    }, () => {  
     //获取页面数据等等   
     that.getDetail(this.orderId);
     ...
    }
  );
 },

不过,每个页面都要这样写,重复代码好多啊,侵入性也强。不如用装饰函数(高大上的说法是装饰者模式)来包装一下:

//filter.js
function identityFilter(pageObj){
  if(pageObj.onShow){
    let _onShow = pageObj.onShow;
    pageObj.onShow = function(){
      service.identityCheck(()=>{
        //跳转到登录页
        wx.redirectTo({
          url: "/pages/common/login/login"
        });
      },()=>{
        //获取页面实例,防止this劫持
        let currentInstance = getPageInstance();
        _onShow.call(currentInstance);
      });
    }
  }
  return pageObj;
}

function getPageInstance(){
  var pages = getCurrentPages();
  return pages[pages.length - 1];
}

exports.identityFilter = identityFilter;

filter.js用以提供过滤器方法,除了现有的用户身份拦截,后续如果需要其他拦截,可以在这个文件增加。然后,在需要用户身份拦截的小程序页面代码里,用filter.identityFilter处理一下就可以了:

//orderDetail.js
let filter = require('filter.js');
Page(filter.identityFilter({
  ...
  onShow: function () {
    //获取页面数据等等
    this.getDetail(this.orderId);
    //...
  },
  ...
}));

使用Promise进行优化

上面的实现中,每次访问页面,都会执行一次获取用户身份的方法(就是上面代码里的service. identityCheck )。其实没有必要,在小程序启动的时候获取一次就行了。也就是说,放在app.js的onLaunch方法里执行。

每个小程序页面实例化时,一般也会执行异步方法,用来获取页面需要的数据。关键在于,我们需要保证,页面的异步方法 必须在 获取用户身份的异步请求 之后执行。

毋容置疑,Promise最擅长处理异步请求的执行顺序了。主子,快放代码粗来:

//app.js
App({
  onLaunch:function(){
    let p = new Promise(function(resolve,reject){
      service.identityCheck(resolve,reject);
    });
    this.globalData.promise = p; 
  },
  ...
  globalData: {
    promise:null,
  }  
});
//filter.js
const appData = getApp().globalData;
function identityFilter(pageObj){
  if(pageObj.onShow){
    let _onShow = pageObj.onShow;
    pageObj.onShow = function(){
      //改动点
      appData.promise.then(()=>{
        //跳转到登录页
        wx.redirectTo({
          url: "/pages/common/login/login"
        });
      },()=>{
        //获取页面实例,防止this劫持
        let currentInstance = getPageInstance();
        _onShow.call(currentInstance);
      });
    }
  }
  return pageObj;
}

小结

基本实现了小程序页面的用户身份拦截器,但是比起laravel的http中间件还是逊色一些:

  • 需要对每个页面代码包装一层。
  • 即使用户身份校验不通过,小程序也并不会阻塞页面的渲染。假如获取用户身份的异步方法一分钟才执行完,小程序页面还是会展示出来,一分钟之后才跳转到登录页。需要自己增加逻辑,比如在这一分钟内,页面展示空白内容。

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

Javascript 相关文章推荐
如何用js控制css中的float的代码
Aug 16 Javascript
js利用与或运算符优先级实现if else条件判断表达式
Apr 15 Javascript
javascript复制对象使用说明
Jun 28 Javascript
jQuery(非HTML5)可编辑表格实现代码
Dec 11 Javascript
JS连连看源码完美注释版(推荐)
Dec 09 Javascript
JQuery设置时间段下拉选择实例
Dec 30 Javascript
JavaScript中使用Object.prototype.toString判断是否为数组
Apr 01 Javascript
浅析BootStrap模态框的使用(经典)
Apr 29 Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
Sep 14 Javascript
令按钮悬浮在(手机)页面底部的实现方法
May 02 Javascript
swiper在angularjs中使用循环轮播失效的解决方法
Sep 27 Javascript
vue使用v-model进行跨组件绑定的基本实现方法
Apr 28 Vue.js
基于js粘贴事件paste简单解析以及遇到的坑
Sep 07 #Javascript
微信小程序实现轮播图效果
Sep 07 #Javascript
使用mint-ui开发项目的一些心得(分享)
Sep 07 #Javascript
JavaScript+CSS相册特效实例代码
Sep 07 #Javascript
AngularJS 打开新的标签页实现代码
Sep 07 #Javascript
基于Cookie常用操作以及属性介绍
Sep 07 #Javascript
基于require.js的使用(实例讲解)
Sep 07 #Javascript
You might like
php 分页函数multi() discuz
2009/06/21 PHP
初品cakephp 入门基础
2012/02/16 PHP
解决更换PHP5.4以上版本后Dedecms后台登录空白问题的方法
2015/10/23 PHP
WordPress免插件实现面包屑导航的示例代码
2020/08/20 PHP
Document 对象的常用方法
2009/07/31 Javascript
jquery 延迟执行实例介绍
2013/08/20 Javascript
关于Jquery操作Cookie取值错误的解决方法
2013/08/26 Javascript
js/jquery判断浏览器的方法小结
2014/09/02 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
微信小程序 教程之模块化
2016/10/17 Javascript
原生js实现可拖动的登录框效果
2017/01/21 Javascript
JS+DIV实现的卷帘效果示例
2017/03/22 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
web前端开发中常见的多列布局解决方案整理(一定要看)
2017/10/15 Javascript
jQuery实现切换隐藏与显示同时切换图标功能
2017/10/29 jQuery
JavaScript 正则命名分组【推荐】
2018/06/07 Javascript
nodejs 十六进制字符串型数据与btye型数据相互转换
2018/07/30 NodeJs
Vue源码探究之状态初始化
2018/11/14 Javascript
webpack4.0+vue2.0利用批处理生成前端单页或多页应用的方法
2019/06/28 Javascript
python实现迭代法求方程组的根过程解析
2019/11/25 Javascript
vue使用screenfull插件实现全屏功能
2020/09/17 Javascript
[51:05]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第一局
2016/03/06 DOTA
[52:27]2018DOTA2亚洲邀请赛 3.31 小组赛B组 paiN vs Secret
2018/04/01 DOTA
Python程序语言快速上手教程
2012/07/18 Python
Python中使用hashlib模块处理算法的教程
2015/04/28 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
Pytorch 实现数据集自定义读取
2020/01/18 Python
TensorFlow加载模型时出错的解决方式
2020/02/06 Python
python获取系统内存占用信息的实例方法
2020/07/17 Python
维多利亚的秘密官方旗舰店:VICTORIA’S SECRET
2018/04/02 全球购物
意大利婴儿产品网上商店:Mukako
2018/10/14 全球购物
一份婚庆公司创业计划书
2014/01/11 职场文书
教师听课评语大全
2014/12/31 职场文书
2015年教师个人业务工作总结
2015/10/23 职场文书
mysql优化
2021/04/06 MySQL
redis实现共同好友的思路详解
2021/05/26 Redis