HBuilder mui入門教程——(5)登入和訪問控制
mui中提供了登入的模板頁,但是對於登入後各個頁面的訪問控制,重新整理等並沒有官方的推薦方案。我在這裡簡單說一種初級的解決方案吧,肯定有不足指出,歡迎批評指正。
第一節中建立移動APP專案的時候選擇的是"mui專案"
,只引入了預設的js和css等檔案,沒有登入模板。要使用預設登入模板,可以建立的時候選擇"mui登入模板"
。現在建立一個名為muiLogin的"mui登入模板"
專案:
可以看到這次多了不少東西。通過manifest.json可以發現,入口檔案時login.html,我們就從login.html開始。
從plusReady函式開始看起。
$.plusReady(function() { plus.screen.lockOrientation("portrait-primary"); var settings = app.getSettings(); var state = app.getState(); var mainPage = $.preload({ "id": 'main', "url": 'main.html' }); var main_loaded_flag = false; mainPage.addEventListener("loaded",function () { main_loaded_flag = true; }); var toMain = function() { //使用定時器的原因: //可能執行太快,main頁面loaded事件尚未觸發就執行自定義事件,此時必然會失敗 var id = setInterval(function () { if(main_loaded_flag){ clearInterval(id); $.fire(mainPage, 'show', null); mainPage.show("pop-in"); } },20); }; //檢查 "登入狀態/鎖屏狀態" 開始 if (settings.autoLogin && state.token && settings.gestures) { $.openWindow({ url: 'unlock.html', id: 'unlock', show: { aniShow: 'pop-in' }, waiting: { autoShow: false } }); } else if (settings.autoLogin && state.token) { toMain(); } else { app.setState(null); //第三方登入 var authBtns = ['qihoo', 'weixin', 'sinaweibo', 'qq']; //配置業務支援的第三方登入 var auths = {}; //... } }
先通過
toMain跳轉主頁面更新使用者資訊
然後是一個跳轉到主頁面的toMain函式,可以看到這裡監聽了main頁面的loaded事件,當main載入完畢後,這裡就將標誌向量main_loaded_flag置為true,toMain中迴圈判斷這個變數,當這裡為true時,觸發main的show事件,然後在main中,show事件的響應函式從app.getState()中讀取使用者名稱,顯示在介面。這就完成了使用者登入後主介面的使用者名稱顯示。
app.getState和app.setState
上面用到了app.getState(),這是定義在js/app.js中的,不妨去看下都做了什麼。
/** * 獲取當前狀態 **/ owner.getState = function() { var stateText = localStorage.getItem('$state') || "{}"; return JSON.parse(stateText); }; /** * 設定當前狀態 **/ owner.setState = function(state) { state = state || {}; localStorage.setItem('$state', JSON.stringify(state)); };
可以看到這兩個是對localStorage的存取做了封裝,是一個字典物件,這是個很不錯的想法,可以將使用者登入後的所有狀態資訊記錄在state裡面,包括使用者資訊,是否自動登入,使用者餘額,訂單列表頁的最新和最舊ID等都儲存下來,使用者登出後直接把state置為null就可以了,再次登入後再設定state。
上面的登入就是這樣做的,登入成功後儲存使用者資訊在state裡面,然後觸發涉及使用者的main頁面的事件,main頁面裡自定義事件的響應函式可以從state裡讀取資訊並更新。
登入部分
登入這裡先判斷了是否執行自動登入以及是否設定了手勢解鎖。然後按情況決定是手勢解鎖還是直接登入或者顯示登入介面。
點選登入按鈕後,會呼叫app的login函式驗證登入資訊,驗證正確就會呼叫toMain跳轉到主頁面。
訪問控制
登陸部分很明瞭,但是大部分app是允許使用者在不登入的情況下瀏覽部分頁面的,如果使用者訪問的頁面需要登入再自動跳轉到登入頁面。
這裡就需要對登入驗證做個封裝,畢竟每次驗證頁面的時候,都從state裡面判斷一下使用者是否登入了,以及是否允許自動登入,自動登入是否成功,是否顯示登入介面是件很麻煩的事。
我們希望達到這種效果,如果使用者點選"我的"
頁面,通過以下程式碼自動進行訪問控制:
mui('#my')[0].addEventListener('tap',function(){
app.loginRequired(function(){
mui.openWindow({
url:'my.html',
id:'my'
});
});
});
只多了一行:app.loginRequired
,如果某個頁面需要登入才能訪問,就把登入後執行的程式碼作為回撥函式傳給app.loginRequired
,由它進行自動登入和登入不成功的跳轉。
/**
* 要求登陸後才能執行回撥函式
* @param {Object} callback 已登入或自動登入成功執行,否則跳轉到登入介面
*/
owner.loginRequired=function(callback){
var state=owner.getState();
if(state.isLogin){//已登入,直接執行
callback();
}else{
owner.tryAutoLogin(function(data){
if(data.Code==1){//自動登入成功則執行回撥函式
callback();
}else{//自動登入失敗,顯示登入頁面
var v=plus.webview.getWebviewById('login');
if(!v){
mui.toast('error:cannot find login');
}else{
v.show('slide-in-right',300);
}
}
});
}
};
為了確保上面能找到登入頁面,需要先預載入login頁面,由於主頁面是main,不再是login了,可以在main裡面預載入login.html,然後這裡就會找到login的webview
看到裡面呼叫了一個tryAutoLogin
的自動登入函式,這個函式嘗試用儲存在state中的上次登入資訊自動ajax請求伺服器登入。
/**
* 嘗試自動登入
* @param {Function} callback 回撥函式,接收一個字典引數data,data.Code>0表示登入成功
*/
owner.tryAutoLogin=function (callback){
var state=owner.getState();
if(state.isLogin){
callback({Code:1});
return;
}
var user=JSON.parse(localStorage.getItem('$user'));
//需要在登入或註冊成功時將使用者資訊儲存在localStorage中
var settings=owner.getSettings();
if (settings.autoLogin&&user&&user.name) {
owner.login(user,callback);
}else{
callback({Code:-1});
}
}
tryAutoLogin的主要工作就是判斷是否允許自動登入,如果允許就呼叫login方法嘗試登入,並將回撥函式也傳遞過去。
/**
* 使用者登入
**/
owner.login = function(loginInfo, callback) {
callback = callback || $.noop;
loginInfo.Method='Login';//告訴伺服器執行哪個函式
$.ajax(owner.server,{//伺服器地址
data:loginInfo,
success:function(data){
if(data.Code==1){
plus.nativeUI.toast('登入成功');
var state=owner.defaultState;//登入後用預設State覆蓋現有的State
state.isLogin=true;//標記已登入
state.user=data.Data;//儲存使用者資訊
owner.setState(state);
//儲存登入資訊
localStorage.setItem('$user', JSON.stringify(loginInfo));
//通知資金變動頁面重新整理
var moneyChange=plus.webview.getWebviewById('moneyChange');
if(moneyChange){
mui.fire(moneyChange,'show');
}
//通知其他使用者相關頁面更新
}
callback(data);
},
error:function(msg){
callback({
Code:-3,
Msg:'無法連線到伺服器'
});
}
});
};
login函式中有一句是defaultState,這個就是儲存的預設使用者狀態,使用者登出再次登入後就應該用這個替換上次使用者的狀態。防止資訊錯亂。
通過以上三個函式,就完成了頁面登入的自動驗證和訪問控制,使得整體邏輯比較清晰,程式碼如有bug歡迎指正。