隱藏框架只是非同步互動的載體,它僅負責資訊的傳輸,而互動的核心應該是一種資訊處理機制,這樣處理機制就是回撥函數。
所謂回撥函數,就是用戶端頁面中的一個普通函數,但是該函數是在伺服器端被呼叫,並負責處理伺服器端響應的資訊。
在非同步互動過程中,經常需要資訊的雙向互動,而不僅僅是接收伺服器端的資訊。下面範例演示如何把用戶端的資訊傳遞給伺服器端,同時讓伺服器準確接收用戶端資訊。本例初步展現了非同步互動中請求和響應的完整過程,其中回撥函數的處理又是整個案例的焦點。
操作步驟
1) 構建一個框架集(index.htm)。
<html>
<head>
<title></title>
</head>
<frameset rows="*,0">
<frame scr="main.htm" name="main" />
<frame src="black.htm" name="server" />
</frameset>
<noframes>您的瀏覽器不支援框架集,請升級瀏覽器版本!</nodrames>
</html>
本文件框架集由上下兩個框架組成,第二個框架高度為 0,但是不要設定為 0 畫素高,因為在一些老版本的瀏覽器中會依然顯示。這兩個框架的分工如下:
-
框架 1(main),負責與使用者進行資訊互動。
-
框架 2(server),負責與伺服器進行資訊互動。
使用 <noframes> 標籤相容老版本瀏覽器,使使用者體驗更友好。
2) 在預設狀態下,框架集中第二個框架載入一個空白頁面(black.htm),第一個框架中載入與客戶進行互動的頁面(main.htm)。
第一個框架中主要包含兩個函數:一個是響應使用者操作的回撥函數,另一個是向伺服器傳送請求的事件處理常式。
<html>
<body>
<title>與客戶互動頁面</title>
<script>
function request () { //向伺服器傳送的非同步請求函數
var user = document.getElementById ("user"); //獲取使用者輸入的使用者名稱
var pass = document.getElementById ("pass"); //獲取使用者輸入的密碼
var s = "user=" + user.value + "&pass=" + pass.value; //構造查詢字串
parent.frames[1].location.href = "server.htm?" + s;
//為框架集中第二個框架載入伺服器端請求檔案,,並附加查詢字串,傳送用戶端資訊,以實現非同步資訊的雙向互動
}
function callback (b, n) { //非同步互動的回撥函數
if (b) { //如果引數b為真,說明輸入資訊正確
//獲取第一個框架中body元素的參照指標,以實現向其中插入資訊
var e = document.getElementsByTagName ("body") [o];
//在互動頁面中插入新的互動資訊
e.innerHTML = "<h1>" + n + "</h1><p>你好,歡迎登入站點</p>";
} else { //如果引數b為假,說明輸入資訊不正確
console.log("您輸入的使用者名稱或密碼有誤,請重新輸入"); //提示重新輸入資訊
var user = parent.frames[0].document.getElementById ("user"); //獲取第一個框架中的使用者名稱文字方塊
var pass = parent.frames[0].document.getElementById ("pass"); //獲取第一個框架中的密碼文字方塊
user.value = ""; //清空使用者名稱文字方塊中的值
pass.value = ""; //清空密碼文字方塊中的值
}
}
window.load = function () { //頁面初始化處理常式
var b = document.getElementById ("submit"); //獲取【提交】按鈕
b.onclick = request; //係結滑鼠單擊事件處理常式
}
</script>
</head>
<body>
<h1>使用者登入</h1>
使用者名稱 <input name="" id="user" type="text"><br /><br />
密碼 <input name="" id="pass" type="password"><br /><br />
<input name="submit" type="button" id="submit" value="提交" />
</body>
</html>
由於回撥函數是在伺服器端檔案中被呼叫的,所以物件作用域的範圍就發生了變化,此時應該指明它的框架集和框架名或序號,否則在頁面操作中會找不到指定的元素。
3) 在伺服器端的檔案中設計響應處理常式,該函數將分解 HTTP 傳遞過來的 URL 資訊,獲取查詢字串,並根據查詢的字串中的使用者名稱和密碼判斷當前輸入的資訊是否正確,並決定具體響應的資訊。
<html>
<head>
<title>伺服器端響應和處理頁面</title>
<script>
window.onload = function () { //伺服器響應處理常式,當該頁面被請求載入時觸發
var query = location.search.substring (1); //獲取URL中所包含的查詢字串
var a = query.split ("&"); //劈開查詢字串為陣列
var o = {}; //臨時物件直接量
for (var i = 0; i < a.length; i ++) { //遍歷查詢字串陣列
var pos = a[i].indexOf ("="); //找到等號的下標位置
if (pos == -1) continue; //如果沒有等號,則忽略
var name = a[i].substring (0, pos); //獲取等號前面的字串
var value = a[i].substring (pos + 1); //獲取等號後面的字串
o[name] = unescape (value); //把名/值對傳遞給物件
}
var n, b;
//如果使用者名稱等於“admin”,則記錄該資訊,否則設定為null
((o["user"]) && o["user"] == "admin") ? (n = o["user"]) : (n = null);
//如果密碼存在,且等於“123456”,則設定變數b為true,否則為false
((o["pass"]) && o["pass"] == "123456") ? (b = true) : (b = false);
//呼叫用戶端框架集中第1個框架中的回撥函數,並把處理的資訊傳遞給它
parent.frames[0].callback(b, n);
}
</script>
</head>
<body>
<h1>伺服器端響應和處理頁面</h1>
</body>
</html>
在實際開發中,伺服器端檔案一般為動態伺服器型別的檔案,並藉助伺服器端指令碼來獲取使用者的資訊,然後決定響應的內容,如,查詢資料庫、返回查詢內容等。本範例以簡化的形式演示非同步通訊的過程,因此沒有採用伺服器技術。
4) 預覽框架集,在客戶互動頁面中輸入使用者的登入資訊,當向伺服器提交請求之後伺服器首先接收從用戶端傳遞過來的資訊並進行處理,然後呼叫用戶端的回撥函數把處理後的資訊響應回去。由於安全的原因,谷歌等瀏覽器不支援頁面之間的連續跳轉。在 IE 下,必須點選“允許阻止的內容”,方可在 IE 下正常執行。演示效果如圖所示: