HBuilder mui登陸和訪問控制教程css
mui中提供了登陸的模板頁,可是對於登陸後各個頁面的訪問控制,刷新等並無官方的推薦方案。我在這裏簡單說一種初級的解決方案吧,確定有不足指出,歡迎批評指正。html
第一節中建立移動APP項目的時候選擇的是"mui項目",只引入了默認的js和css等文件,沒有登陸模板。要使用默認登陸模板,能夠建立的時候選擇"mui登陸模板"。如今建立一個名爲muiLogin的"mui登陸模板"項目:java
能夠看到此次多了很多東西。經過manifest.json能夠發現,入口文件時login.html,咱們就從login.html開始。web
從plusReady函數開始看起。ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
<code><code><code><code>$.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 = {};
//...
}
}
</code></code></code></code>
|
先經過.preload預加載了main.html(就是mui,這是個閉包函數,mui做爲參數$傳進來的,詳情百度JavaScript 閉包)。
json
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中的,不妨去看下都作了什麼。
閉包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<code><code><code><code><code>
/**
* 獲取當前狀態
**/
owner.getState = function() {
var stateText = localStorage.getItem(
'$state'
) ||
"{}"
;
return
JSON.parse(stateText);
};
/**
* 設置當前狀態
**/
owner.setState = function(state) {
state = state || {};
localStorage.setItem(
'$state'
, JSON.stringify(state));
};
</code></code></code></code></code>
|
能夠看到這兩個是對localStorage的存取作了封裝,是一個字典對象,這是個很不錯的想法,能夠將用戶登陸後的全部狀態信息記錄在state裏面,包括用戶信息,是否自動登陸,用戶餘額,訂單列表頁的最新和最舊ID等都保存下來,用戶註銷後直接把state置爲null就能夠了,再次登陸後再設置state。
app
上面的登陸就是這樣作的,登陸成功後保存用戶信息在state裏面,而後觸發涉及用戶的main頁面的事件,main頁面裏自定義事件的響應函數能夠從state裏讀取信息並更新。
ide
登陸部分
登陸這裏先判斷了是否運行自動登陸以及是否設置了手勢解鎖。而後按狀況決定是手勢解鎖仍是直接登陸或者顯示登陸界面。
點擊登陸按鈕後,會調用app的login函數驗證登陸信息,驗證正確就會調用toMain跳轉到主頁面。
訪問控制
登錄部分很明瞭,可是大部分app是容許用戶在不登陸的狀況下瀏覽部分頁面的,若是用戶訪問的頁面須要登陸再自動跳轉到登陸頁面。
這裏就須要對登陸驗證作個封裝,畢竟每次驗證頁面的時候,都從state裏面判斷一下用戶是否登陸了,以及是否容許自動登陸,自動登陸是否成功,是否顯示登陸界面是件很麻煩的事。
咱們但願達到這種效果,若是用戶點擊
"個人"頁面,經過如下代碼自動進行訪問控制:
1
2
3
4
5
6
7
8
9
|
<code><code><code><code><code><code><code>mui(
'#my'
)[
0
].addEventListener(
'tap'
,function(){
app.loginRequired(function(){
mui.openWindow({
url:
'my.html'
,
id:
'my'
});
});
});
</code></code></code></code></code></code></code>
|
只多了一行:
app.loginRequired,若是某個頁面須要登陸才能訪問,就把登陸後執行的代碼做爲回調函數傳給
app.loginRequired,由它進行自動登陸和登陸不成功的跳轉。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<code><code><code><code><code><code><code><code><code><code>
/**
* 要求登錄後才能執行回調函數
* @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
);
}
}
});
}
};
</code></code></code></code></code></code></code></code></code></code>
|
爲了確保上面能找到登陸頁面,須要先預加載login頁面,因爲主頁面是main,再也不是login了,能夠在main裏面預加載login.html,而後這裏就會找到login的webview
看到裏面調用了一個
tryAutoLogin的自動登陸函數,這個函數嘗試用保存在state中的上次登陸信息自動ajax請求服務器登陸。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<code><code><code><code><code><code><code><code><code><code><code><code>
/**
* 嘗試自動登陸
* @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
});
}
}
</code></code></code></code></code></code></code></code></code></code></code></code>
|
tryAutoLogin的主要工做就是判斷是否容許自動登陸,若是容許就調用login方法嘗試登陸,並將回調函數也傳遞過去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
<code><code><code><code><code><code><code><code><code><code><code><code><code>
/**
* 用戶登陸
**/
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:
'沒法鏈接到服務器'
});
}
});
};
</code></code></code></code></code></code></code></code></code></code></code></code></code>
|
login函數中有一句是defaultState,這個就是存儲的默認用戶狀態,用戶註銷再次登陸後就應該用這個替換上次用戶的狀態。防止信息錯亂。
經過以上三個函數,就完成了頁面登陸的自動驗證和訪問控制,使得總體邏輯比較清晰,代碼若有bug歡迎指正。