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


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 相关文章推荐
基于jquery的拖动布局插件
Nov 25 Javascript
js Array对象的扩展函数代码
Apr 24 Javascript
很全面的JavaScript常用功能汇总集合
Jan 22 Javascript
原生js实现百叶窗效果及原理介绍
Apr 12 Javascript
Angular ng-repeat遍历渲染完页面后执行其他操作详细介绍
Dec 13 Javascript
JavaScript实现按键精灵的原理分析
Feb 21 Javascript
webpack打包单页面如何引用的js
Jun 07 Javascript
vue下拉列表功能实例代码
Apr 08 Javascript
WebSocket的通信过程与实现方法详解
Apr 29 Javascript
js 实现在2d平面上画8的方法
Oct 10 Javascript
Vue 实现手动刷新组件的方法
Feb 19 Javascript
js实现计时器秒表功能
Dec 16 Javascript
基于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 array_map array_multisort 高效处理多维数组排序
2009/06/11 PHP
php输出xml格式字符串(用的这个)
2012/07/12 PHP
php实现简单洗牌算法
2013/06/18 PHP
PHP中UNIX时间戳和日期间的转换与计算实例
2014/11/19 PHP
PHP向socket服务器收发数据的方法
2015/01/24 PHP
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
PHP多进程编程总结(推荐)
2016/07/18 PHP
php使用curl下载指定大小的文件实例代码
2017/09/30 PHP
Javascript 面向对象(二)封装代码
2012/05/23 Javascript
javascript 实现简单的table排序及table操作练习
2012/12/28 Javascript
js代码延迟一定时间后执行一个函数的实例
2017/02/15 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
vue+element实现批量删除功能的示例
2018/02/28 Javascript
angularJs提交文本框数据到后台的方法
2018/10/08 Javascript
JavaScript函数式编程(Functional Programming)声明式与命令式实例分析
2019/05/21 Javascript
关于vue3默认把所有onSomething当作v-on事件绑定的思考
2020/05/15 Javascript
[58:46]OG vs NAVI 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
布同自制Python函数帮助查询小工具
2011/03/13 Python
在主机商的共享服务器上部署Django站点的方法
2015/07/22 Python
python魔法方法-属性转换和类的表示详解
2016/07/22 Python
利用Python爬取可用的代理IP
2016/08/18 Python
Python读写Json涉及到中文的处理方法
2016/09/12 Python
Python实现PS图像调整黑白效果示例
2018/01/25 Python
对python中raw_input()和input()的用法详解
2018/04/22 Python
Pandas之DataFrame对象的列和索引之间的转化
2019/06/25 Python
pandas DataFrame的修改方法(值、列、索引)
2019/08/02 Python
Django中URL的参数传递的实现
2019/08/04 Python
Python目录和文件处理总结详解
2019/09/02 Python
Python中的With语句的使用及原理
2020/07/29 Python
matplotlib grid()设置网格线外观的实现
2021/02/22 Python
IE下实现类似CSS3 text-shadow文字阴影的几种方法
2011/05/11 HTML / CSS
埃弗顿足球俱乐部官方网上商店:Everton Direct
2018/01/13 全球购物
初级会计求职信范文
2014/02/15 职场文书
会计演讲稿范文
2014/05/23 职场文书
计算机实训报告总结
2014/11/05 职场文书
2016年社区植树节活动总结
2016/03/16 职场文书