19-2 洏疆 iframe DPBЧ

事實上,非同步傳輸的功能,並非一定必須靠 AJAX 來達成。本小節將說明如何使用隱藏式的 iframe 的方式來達到類似的功能。

首先,我們先看一個範例:

Example(ajax/asyncViaIFrame01.htm):

在上述範例中,當你點選「顯示子網頁相關資訊...」後,就會看到伺服器的相關資訊已經顯示在網頁上,如下:

而這整個過程並沒有經由網頁的重載來達成。此範例的原始碼如下:

原始檔(ajax/asyncViaIFrame01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>使用 iframe 來進行非同步傳輸的簡單範例</h2>
<hr>

<script>
// 顯示從伺服器回傳的資訊,此函數只會被隱藏的子網頁所呼叫。
function showRetrievedInfo(serverName, serverUrl, serverIp) {
	document.getElementById('show01').innerHTML=serverName;		// 顯示 serverName
	document.getElementById('show02').innerHTML=serverUrl;		// 顯示 serverUrl
	document.getElementById('show03').innerHTML=serverIp;		// 顯示 serverIp
//	document.getElementById('myHiddenFrame').src='';		// 清除 iframe 的網址
}

// 母網頁表單的回應函數,只被母網頁呼叫。
function mainCallBack(){
	var iframe = document.getElementById('myHiddenFrame');	// 取得 iframe 物件
	iframe.src = "serverAction01.asp";	// 設定 iframe 的網址為 serverAction01.asp 並執行此 asp 網頁
}
</script>

<input type="button" value="顯示子網頁相關資訊..." onClick="mainCallBack()">
<p>子網頁伺服器網域名稱:<div id="show01"></div>
<p>子網頁網址:<div id="show02"></div>
<p>子網頁伺服器 IP:<div id="show03"></div>

<iframe id="myHiddenFrame" style="display:none"></iframe>

</body>
</html>

在上述原始碼的尾端,我們可以看到一個隱藏的 iframe:

<iframe id="myHiddenFrame" style="display:none"></iframe> 這個隱藏的 iframe 就是我們偷偷請伺服器執行程式碼之處。為方便說明,我們將原範例網頁稱為「母網頁」,而將 iframe 所執行的網頁稱為「子網頁」,由於 iframe 是隱藏的,所以子網頁的結果並不會顯示出來。整個網頁進行非同步傳輸的工作流程如下:
  1. 當使用者點選「顯示子網頁相關資訊...」,瀏覽器會呼叫 mainCallBack(),以設定 iframe 的網頁為 serverAction01.asp,換句話說,此時伺服器將會執行 serverAction01.asp,原始碼如下:

    原始檔(ajax/serverAction01.asp):(灰色區域按兩下即可拷貝)
    <%@language=jscript%>
    <%//用於隱藏子網頁的程式碼,負責抓取 ServerVariables%>
    <%
    // 進行伺服器端的運算
    serverName=Request.ServerVariables("SERVER_NAME");
    serverUrl = Request.ServerVariables("URL");
    serverIp = Request.ServerVariables("LOCAL_ADDR");
    %>
    <script>
    // 呼叫母網頁的函數 showRetrievedInfo(),以便在母網頁顯示相關資訊
    window.parent.showRetrievedInfo('<%=serverName%>', '<%=serverUrl%>', '<%=serverIp%>');
    </script>
    

    此 ASP 程式碼會設定 serverName(子網頁伺服器網域名稱)、serverUrl(子網頁網址)、serverIp(子網頁伺服器 IP)三個變數的值,並將此值送到瀏覽器的 JavaScript 函數 window.parent.showRetrievedInfo()。

  2. 當隱藏式的 iframe 收到伺服器回傳的資料後,瀏覽器將會執行 window.parent.showRetrievedInfo(),亦即呼叫母網頁的函數 showRetrievedInfo()。
  3. 母網頁執行 showRetrievedInfo(),並將結果顯示於母網頁內,其中 document.getElementById('show01').innerHTML=serverName; 的功能是將 id 為 show01 的物件的內容填入 serverName 變數的值,換句話說,母網頁的 <div id="show01"></div> 就會被代換成 <div id="show01">neural.cs.nthu.edu.tw</div> 因而我們就可以立刻看到由伺服器回傳的網域名稱,依此類推。
使用 iframe 來進行非同步傳輸,是一個簡單可行的方式,足以對付一般基本應用。但是此方法最大的缺點,是子網頁無法支援 post 的資料傳送方式,若要解決這個問題,可以使用後續小節所要說明的 AJAX 方法來達成。

在下面這個範例中,我們說明如何使用類似的方法,來對資料庫進行查詢,並以非同步的方式將查詢結果顯示於同一個網頁。由於下達查詢時,子網頁必須取得相關的 SQL 指令,此部分我們是採用 get 的方式來將 SQL 指令傳送至子網頁。範例如下:

Example(ajax/asyncViaIFrame02.asp):

在上述範例中,我們先列出資料庫 ajax/basketball.mdb 的內容,共包含兩個資料表,分別是 Player 和 Team。我們可以直接在文字欄位輸入 SQL 指令,就可以直接利用隱藏式 iframe 的方式來顯示資料庫查詢結果,而不必經由網頁重載來達成此功能。例如,若我們直接點選「進行查詢」,所得到的結果如下:

此範例母網頁的原始碼如下:

原始檔(ajax/asyncViaIFrame02.asp):(灰色區域按兩下即可拷貝)
<%@ language="jscript" %>
<% title="使用 iframe 來進行非同步傳輸的進階範例:資料庫查詢" %>
<!--#include file="../head.inc"-->
<hr>

<script>
// 顯示從伺服器回傳的資訊,此函數只會被隱藏的子網頁所呼叫。
function showQueryResult(result){
	document.getElementById('showSqlResult').innerHTML=result;	// 顯示查詢結果
}

// 母網頁表單的回應函數,只被母網頁呼叫。
function sendQuery(){
	var sqlCommand = document.getElementById('sqlCommand');
	var sql=sqlCommand.value;
	var iframe = document.getElementById('hiddenIFrame');	// 取得 iframe 物件
	iframe.src = "serverAction02.asp?sql="+escape(sql);	// 設定 iframe 的網址,其中 sql 必須先經過 escape() 函數的編碼
}
</script>

<script language=jscript runat=server src=sqlUtility.fun></script>
<% database = "basketball.mdb"; %>
資料庫完整內容:
<center>
<table border=1>
<tr>
<th colspan=2 align=center>
資料庫 "<%=database%>"
<tr>
<td align=center> 資料表 "Player" 的內容
<td align=center> 資料表 "Team" 的內容
<tr>
<td> <%=getQueryResult(database, "select * from Player")%>
<td> <%=getQueryResult(database, "select * from Team")%>
</table>
</center>
<p>
請輸入你的SQL指令:<br>
<input id=sqlCommand size=80 type=text value="SELECT * FROM Player WHERE Name LIKE '陳%'"><br>
<input type="button" value="進行查詢" onClick="sendQuery()">
<p>
查詢結果:<div id="showSqlResult"></div>

<iframe id="hiddenIFrame" style="display:none"></iframe>

<hr>
<!--#include file="../foot.inc"-->

在此範例中,請特別注意兩點:

而子網頁的原始碼如下:

原始檔(ajax/serverAction02.asp):(灰色區域按兩下即可拷貝)
<%@language=jscript%>
<%//用於隱藏子網頁的程式碼,負責查詢資料庫%>
<script language=jscript runat=server src=sqlUtility.fun></script>
<%
database="basketball.mdb";
sql=Request("sql")+"";
if (sql.search(/select/i)<0)	// 檢查是否以 select 開頭
	outStr="<font color=red>SQL command not started with SELECT is disabled!</font>";
else 
	outStr=getQueryResult(database, sql);
%>
<script>
// 呼叫母網頁的函數 showQueryResult(),以便在母網頁顯示相關資訊
window.parent.showQueryResult('<%=outStr%>');
</script>

由於我們不希望使用者去修改資料庫,因此我們會使用通用運算式來檢查 SQL 指令,若不是以 "select" 開頭,則認定是不合法的 SQL 指令並回傳警告訊息「SQL command not started with SELECT is disabled!」。


JScript 程式設計與應用:用於伺服器端的 ASP 環境