微信小程序之(zhī)頁面攔截器 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

微信小程序之(zhī)頁面攔截器

發表時(shí)間:2021-4-30

發布人(rén):融晨科技

浏覽次數:358

場景

  1. 小程序有52個(gè)頁面,其中13個(gè)頁面無需任何身份,另外39個(gè)頁面需要(yào / yāo)系統角色。對于(yú)這(zhè)39個(gè)頁面,如果微信用戶沒有系統角色,則跳轉到(dào)登錄頁。
  2. 是(shì)否有系統角色信息需要(yào / yāo)通過異步請求來(lái)獲取。

需求分析&實現

對需求進行抽象,其實要(yào / yāo)的(de)就(jiù)是(shì)一個(gè)過濾器,對小程序頁面的(de)訪問進行過濾,符合條件的(de)通過,不(bù)符合條件進行其他(tā)處理。

使用過php的(de)laravel框架的(de)童鞋,肯定一下子(zǐ)就(jiù)聯想到(dào)了(le/liǎo)laravel框架的(de)http中間件:
HTTP 中間件提供一個(gè)方便的(de)機制來(lái)過濾進入應用程序的(de) HTTP 請求,例如,Laravel 默認包含了(le/liǎo)一個(gè)中間件來(lái)檢驗用戶身份驗證,如果用戶沒有經過身份驗證,中間件會将用戶導向登錄頁面,然而(ér),如果用戶通過身份驗證,中間件将會允許這(zhè)個(gè)請求進一步繼續前進。當然,除了(le/liǎo)身份驗證之(zhī)外,中間件也(yě)可以(yǐ)被用來(lái)執行各式各樣的(de)任務,CORS 中間件負責替所有即将離開程序的(de)響應加入适當的(de)響應頭,一個(gè)日志中間件可以(yǐ)記錄所有傳入應用程序的(de)請求。

令人(rén)憂桑的(de)是(shì),微信小程序并沒有提供針對Page實例的(de)中間件機制。所以(yǐ)隻能從Page實例的(de)生命周期處下手。

對于(yú)onLoad,一個(gè)頁面隻會調用一次;對于(yú)onShow,每次打開頁面(比如小程序從後台轉到(dào)前台)都會調用一次。

在(zài)onLoad或者onShow鈎子(zǐ)函數裏,對用戶身份進行校驗,通過後則拉取該頁面需要(yào / yāo)的(de)數據,否則跳轉到(dào)登錄頁。

//orderDetail.js
onShow: function () {
    let that = this;
    //身份校驗
    service.identityCheck(() => {
          //跳轉到(dào)登錄頁
          wx.redirectTo({
            url: "/pages/common/login/login"
          });
        }, () => {    
          //獲取頁面數據等等      
          that.getDetail(this.orderId);
          ...
        }
   );
  },

不(bù)過,每個(gè)頁面都要(yào / yāo)這(zhè)樣寫,重複代碼好多啊,侵入性也(yě)強。不(bù)如用裝飾函數(高大(dà)上(shàng)的(de)說(shuō)法是(shì)裝飾者模式)來(lái)包裝一下:

//filter.js
function identityFilter(pageObj){
    if(pageObj.onShow){
        let _onShow = pageObj.onShow;
        pageObj.onShow = function(){
            service.identityCheck(()=>{
                //跳轉到(dào)登錄頁
                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用以(yǐ)提供過濾器方法,除了(le/liǎo)現有的(de)用戶身份攔截,後續如果需要(yào / yāo)其他(tā)攔截,可以(yǐ)在(zài)這(zhè)個(gè)文件增加。然後,在(zài)需要(yào / yāo)用戶身份攔截的(de)小程序頁面代碼裏,用filter.identityFilter處理一下就(jiù)可以(yǐ)了(le/liǎo):

//orderDetail.js
let filter = require('filter.js');
Page(filter.identityFilter({
    ...
    onShow: function () {
        //獲取頁面數據等等
        this.getDetail(this.orderId);
        //...
    },
    ...
}));

使用Promise進行優化

上(shàng)面的(de)實現中,每次訪問頁面,都會執行一次獲取用戶身份的(de)方法(就(jiù)是(shì)上(shàng)面代碼裏的(de)service. identityCheck )。其實沒有必要(yào / yāo),在(zài)小程序啓動的(de)時(shí)候獲取一次就(jiù)行了(le/liǎo)。也(yě)就(jiù)是(shì)說(shuō),放在(zài)app.js的(de)onLaunch方法裏執行。

每個(gè)小程序頁面實例化時(shí),一般也(yě)會執行異步方法,用來(lái)獲取頁面需要(yào / yāo)的(de)數據。關鍵在(zài)于(yú),我們需要(yào / yāo)保證,頁面的(de)異步方法 必須在(zài) 獲取用戶身份的(de)異步請求 之(zhī)後執行。

毋容置疑,Promise最擅長處理異步請求的(de)執行順序了(le/liǎo)。主子(zǐ),快放代碼粗來(lái):

//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 = https://www.wxapp-union.com/getApp().globalData;
function identityFilter(pageObj){
    if(pageObj.onShow){
        let _onShow = pageObj.onShow;
        pageObj.onShow = function(){
            //改動點
            appData.promise.then(()=>{
                //跳轉到(dào)登錄頁
                wx.redirectTo({
                    url: "/pages/common/login/login"
                });
            },()=>{
                //獲取頁面實例,防止this劫持
                let currentInstance = getPageInstance();
                _onShow.call(currentInstance);
            });
        }
    }
    return pageObj;
}

小結

基本實現了(le/liǎo)小程序頁面的(de)用戶身份攔截器,但是(shì)比起laravel的(de)http中間件還是(shì)遜色一些:

  1. 需要(yào / yāo)對每個(gè)頁面代碼包裝一層。
  2. 即使用戶身份校驗不(bù)通過,小程序也(yě)并不(bù)會阻塞頁面的(de)渲染。假如獲取用戶身份的(de)異步方法一分鍾才執行完,小程序頁面還是(shì)會展示出(chū)來(lái),一分鍾之(zhī)後才跳轉到(dào)登錄頁。需要(yào / yāo)自己增加邏輯,比如在(zài)這(zhè)一分鍾内,頁面展示空白内容。

嗯,對小程序的(de)新特性保持關注,後面看看怎麽改進~

相關案例查看更多