微信小程序之頁面攔截器

場景

小程序有52個(gè)頁面,其中13個(gè)頁面無需任何身份,另外39個(gè)頁面需要系統(tǒng)角色。對(duì)于這39個(gè)頁面,如果微信用戶沒有系統(tǒng)角色,則跳轉(zhuǎn)到登錄頁。
是否有系統(tǒng)角色信息需要通過異步請(qǐng)求來獲取。

需求分析&實(shí)現(xiàn)

對(duì)需求進(jìn)行抽象,其實(shí)要的就是一個(gè)過濾器,對(duì)小程序頁面的訪問進(jìn)行過濾,符合條件的通過,不符合條件進(jìn)行其他處理。

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

令人憂桑的是,微信小程序并沒有提供針對(duì)Page實(shí)例的中間件機(jī)制。所以只能從Page實(shí)例的生命周期處下手。

對(duì)于onLoad,一個(gè)頁面只會(huì)調(diào)用一次;對(duì)于onShow,每次打開頁面(比如小程序從后臺(tái)轉(zhuǎn)到前臺(tái))都會(huì)調(diào)用一次。在onLoad或者onShow鉤子函數(shù)里,對(duì)用戶身份進(jìn)行校驗(yàn),通過后則拉取該頁面需要的數(shù)據(jù),否則跳轉(zhuǎn)到登錄頁。

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

不過,每個(gè)頁面都要這樣寫,重復(fù)代碼好多啊,侵入性也強(qiáng)。不如用裝飾函數(shù)(高大上的說法是裝飾者模式)來包裝一下:

//filter.js
function identityFilter(pageObj){
    if(pageObj.onShow){
        let _onShow = pageObj.onShow;
        pageObj.onShow = function(){
            service.identityCheck(()=>{
                //跳轉(zhuǎn)到登錄頁
                wx.redirectTo({
                    url: "/pages/common/login/login"
                });
            },()=>{
                //獲取頁面實(shí)例,防止this劫持
                let currentInstance = getPageInstance();
                _onShow.call(currentInstance);
            });
        }
    }
    return pageObj;
}

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

exports.identityFilter = identityFilter;

filter.js用以提供過濾器方法,除了現(xiàn)有的用戶身份攔截,后續(xù)如果需要其他攔截,可以在這個(gè)文件增加。然后,在需要用戶身份攔截的小程序頁面代碼里,用filter.identityFilter處理一下就可以了:

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

使用Promise進(jìn)行優(yōu)化

上面的實(shí)現(xiàn)中,每次訪問頁面,都會(huì)執(zhí)行一次獲取用戶身份的方法(就是上面代碼里的service. identityCheck )。其實(shí)沒有必要,在小程序啟動(dòng)的時(shí)候獲取一次就行了。也就是說,放在app.js的onLaunch方法里執(zhí)行。

每個(gè)小程序頁面實(shí)例化時(shí),一般也會(huì)執(zhí)行異步方法,用來獲取頁面需要的數(shù)據(jù)。關(guān)鍵在于,我們需要保證,頁面的異步方法 必須在 獲取用戶身份的異步請(qǐng)求 之后執(zhí)行。

毋容置疑,Promise最擅長處理異步請(qǐng)求的執(zhí)行順序了。主子,快放代碼粗來:

//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(){
            //改動(dòng)點(diǎn)
            appData.promise.then(()=>{
                //跳轉(zhuǎn)到登錄頁
                wx.redirectTo({
                    url: "/pages/common/login/login"
                });
            },()=>{
                //獲取頁面實(shí)例,防止this劫持
                let currentInstance = getPageInstance();
                _onShow.call(currentInstance);
            });
        }
    }
    return pageObj;
}

小結(jié)

基本實(shí)現(xiàn)了小程序頁面的用戶身份攔截器,但是比起laravel的http中間件還是遜色一些:

1、需要對(duì)每個(gè)頁面代碼包裝一層。

2、即使用戶身份校驗(yàn)不通過,小程序也并不會(huì)阻塞頁面的渲染。假如獲取用戶身份的異步方法一分鐘才執(zhí)行完,小程序頁面還是會(huì)展示出來,一分鐘之后才跳轉(zhuǎn)到登錄頁。需要自己增加邏輯,比如在這一分鐘內(nèi),頁面展示空白內(nèi)容。

嗯,對(duì)小程序的新特性保持關(guān)注,后面看看怎么改進(jìn)~

文章來源:http://www.wxapp-union.com/portal.php?mod=view&aid=2980

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 場景 小程序有52個(gè)頁面,其中13個(gè)頁面無需任何身份,另外39個(gè)頁面需要系統(tǒng)角色。對(duì)于這39個(gè)頁面,如果微信用戶沒...
    獨(dú)愛一樂拉面閱讀 9,914評(píng)論 0 7
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,652評(píng)論 1 32
  • CSRF(Cross-site request forgery,中文為跨站請(qǐng)求偽造)是一種利用網(wǎng)站可信用戶的權(quán)限去...
    mylxsw閱讀 1,073評(píng)論 1 11
  • Getting Started Burp Suite 是用于攻擊web 應(yīng)用程序的集成平臺(tái)。它包含了許多工具,并為...
    Eva_chenx閱讀 29,243評(píng)論 0 14
  • 昨晚夢見你在我面前吹過的那么多的牛逼終于實(shí)現(xiàn)了一個(gè),可是那時(shí)候我已經(jīng)不在是你的她,已經(jīng)沒有那么多的奢望,你成功就好
    相逢是孤島閱讀 275評(píng)論 0 0

友情鏈接更多精彩內(nèi)容