日韩天天综合网_野战两个奶头被亲到高潮_亚洲日韩欧美精品综合_av女人天堂污污污_视频一区**字幕无弹窗_国产亚洲欧美小视频_国内性爱精品在线免费视频_国产一级电影在线播放_日韩欧美内地福利_亚洲一二三不卡片区

如何掌握AJAX之AJAX通訊技術(shù)_AJAX教程

編輯Tag賺U幣
教程Tag:暫無(wú)Tag,歡迎添加,賺取U幣!

推薦:如何用AJAX打造博客無(wú)刷新搜索
如果你對(duì)AJAX不是很了解,可以先看看這篇教程: 《AJAX初體驗(yàn)之上手篇》 。 現(xiàn)在博客很流行,相信應(yīng)該上網(wǎng)時(shí)間稍微長(zhǎng)點(diǎn)的朋友都會(huì)在這或者在那的有一個(gè)自己的博客。對(duì)于一些有一定能力的朋友,可能更喜歡自己去下載一個(gè)博客程序來(lái)架設(shè)一個(gè)自己的博客,而不是

當(dāng)在網(wǎng)上沖浪時(shí),將在瀏覽器和服務(wù)器之間存在大量的請(qǐng)求。最初,所有的這種請(qǐng)求都是在用戶做出需要這一步驟的明顯操作時(shí)發(fā)生的。Ajax技術(shù)將開(kāi)發(fā)人員從等待用戶做出這樣的操作中解放出來(lái),允許他在任何時(shí)間創(chuàng)建一個(gè)對(duì)服務(wù)器的調(diào)用。
Ajax通信支持許多不同的技術(shù)。每一種技術(shù)都有自己的優(yōu)點(diǎn)和缺點(diǎn),因此了解什么情況使用哪一種技術(shù)是很重要的。

  隱藏幀技術(shù)

  隨著HTML幀的引入,隱藏幀(hidden frame)技術(shù)也應(yīng)運(yùn)而生了。該技術(shù)后面的基本想法是創(chuàng)建一個(gè)幀集,其中包含用于客戶端—服務(wù)器通信的隱藏幀�?梢酝ㄟ^(guò)將幀的寬度或高度設(shè)置為0像素來(lái)隱藏一個(gè)幀,以使其不顯示。盡管一些早期的瀏覽器(諸如Netscape 4)不能夠完全隱藏幀,經(jīng)常會(huì)留下一些明顯的幀邊框,但該技術(shù)還是廣泛地為開(kāi)發(fā)人員所采用。

  1. 模式

  隱藏幀技術(shù)遵循一種特定的四步模式(參見(jiàn)圖2-1)。第一步總是從一個(gè)與用戶交互的Web頁(yè)面中的可見(jiàn)幀開(kāi)始的。顯然,用戶并不知道隱藏幀的存在(在現(xiàn)代瀏覽器中,它是不顯示的),以通常的形式與網(wǎng)頁(yè)進(jìn)行交互。在某些時(shí)間,用戶執(zhí)行了一個(gè)需要從服務(wù)器獲取額外數(shù)據(jù)的操作。當(dāng)這個(gè)操作發(fā)生時(shí),第一步就發(fā)生了:產(chǎn)生一個(gè)對(duì)隱藏幀的JavaScript函數(shù)調(diào)用。這個(gè)調(diào)用可以簡(jiǎn)單地將隱藏幀重定向到另一個(gè)頁(yè)面,或者復(fù)雜地傳送表單數(shù)據(jù)。不管這個(gè)函數(shù)有多復(fù)雜,其結(jié)果都是產(chǎn)生第2步:向服務(wù)器發(fā)送一個(gè)請(qǐng)求。

圖 2-1

  該模式中的第3步是從服務(wù)器上接收一個(gè)響應(yīng)。由于處理的是幀,因此該響應(yīng)必然是另一個(gè)網(wǎng)頁(yè)。該網(wǎng)頁(yè)必須包含從服務(wù)器返回的所請(qǐng)求的數(shù)據(jù),同時(shí)一些JavaScript將把這些數(shù)據(jù)傳給可見(jiàn)的幀。通常,這是通過(guò)在返回的網(wǎng)頁(yè)中分配一個(gè)onload事件處理函數(shù)(event handler)做到的,該網(wǎng)頁(yè)在其全部載入之后調(diào)用可見(jiàn)幀中的函數(shù)(這就是第4步)。當(dāng)數(shù)據(jù)位于可見(jiàn)幀中后,該幀就可以決定如何處理這些數(shù)據(jù)了。

  2. 隱藏幀的GET請(qǐng)求

  我們已經(jīng)闡述了隱藏幀技術(shù)的基本原理,現(xiàn)在將更深入地研究它。對(duì)于任何一種新技術(shù),最好的方法就是通過(guò)具體的實(shí)例來(lái)學(xué)習(xí)。在該實(shí)例中,將創(chuàng)建一個(gè)簡(jiǎn)單的查詢頁(yè)面,客戶服務(wù)代表通過(guò)該頁(yè)面可以查詢客戶的信息。由于這是本書(shū)的第一個(gè)例子,因此它十分的簡(jiǎn)單:用戶輸入客戶ID,然后接收與該客戶相關(guān)的信息。由于該功能通常需要數(shù)據(jù)庫(kù)支持,因此還必須做一些服務(wù)器端的開(kāi)發(fā)。該例子使用的是PHP——這是一種優(yōu)秀的開(kāi)源服務(wù)端語(yǔ)言,還將使用到MySQL(在從www.mysql.org下載)——這是一種與PHP結(jié)合得很好的開(kāi)源數(shù)據(jù)庫(kù)。盡管本例確定為使用MySQL,但只需少量的修改就可以在其他數(shù)據(jù)庫(kù)上運(yùn)行。

  首先,在實(shí)現(xiàn)客戶資料查詢之前,你必須有一個(gè)包含該信息的數(shù)據(jù)庫(kù)表�?梢允褂靡韵耂QL腳本來(lái)創(chuàng)建一個(gè)客戶表:


CREATE TABLE `Customers` (
 `CustomerId` int(11) NOT NULL auto_increment,
 `Name` varchar(255) NOT NULL default '',
 `Address` varchar(255) NOT NULL default '',
 `City` varchar(255) NOT NULL default '',
 `State` varchar(255) NOT NULL default '',
 `Zip` varchar(255) NOT NULL default '',
 `Phone` varchar(255) NOT NULL default '',
 `E-mail` varchar(255) NOT NULL default '',
 PRIMARY KEY (`CustomerId`)
) TYPE=MyISAM COMMENT='Sample Customer Data';

 


  在這張數(shù)據(jù)庫(kù)表中最重要的字段是CustomerId,我們將通過(guò)它來(lái)查詢客戶信息。你可以在www.wrox.com下載這個(gè)腳本以及一些測(cè)試數(shù)據(jù)。當(dāng)建好數(shù)據(jù)庫(kù)表后,就可以將精力轉(zhuǎn)到HTML代碼上了。要使用隱藏幀技術(shù),首先必須創(chuàng)建一個(gè)HTML幀集,例如:

 

 

<frameset rows="100%,0" frameborder="0">
�。糵rame name="displayFrame" src="display.htm" noresize="noresize" />
�。糵rame name="hiddenFrame" src="about:blank" noresize="noresize" />
</frameset>

 


  這部分代碼中最重要的是<frameset/>元素的rows屬性。通過(guò)將其設(shè)置為100%,0,瀏覽器就知道不顯示名為hiddenFrame的第二個(gè)幀了。緊接著,將frameborder屬性設(shè)置為0則是確保每個(gè)幀都沒(méi)有可見(jiàn)的邊框。在幀集聲明中最后一個(gè)重要的步驟是為每個(gè)幀設(shè)置noresize屬性,使得用戶不可能在不經(jīng)意間調(diào)整幀的大小而發(fā)現(xiàn)隱藏幀,隱藏幀的內(nèi)容永遠(yuǎn)不會(huì)成為可顯示的用戶界面的一部分。接下來(lái)要處理的是一個(gè)請(qǐng)求和顯示客戶信息的頁(yè)面。這是一個(gè)相對(duì)簡(jiǎn)單的頁(yè)面,由一個(gè)用來(lái)輸入客戶ID的文本框,一個(gè)執(zhí)行請(qǐng)求的按鈕,以及用來(lái)顯示查詢到的客戶信息的<div>元素所組成:

 

 

<p>Enter customer ID number to retrieve information:</p>
<p>Customer ID: <input type="text" id="txtCustomerId" value="" /></p>
<p><input type="button" value="Get Customer Info"
onclick="requestCustomerInfo()" /></p>
<div id="divCustomerInfo"></div>

 


  注意,按鈕調(diào)用的是名為requestCustomerInfo()的函數(shù),該函數(shù)將負(fù)責(zé)與隱藏幀交互以獲取數(shù)據(jù)。它將獲取文本框中的值,將其添加到getcustomerdata.php的查詢字符串上,以getcustomerdata.php?id=23的格式創(chuàng)建一個(gè)URL。然后將這個(gè)URL指派給隱藏幀,以下就是這個(gè)函數(shù)的代碼:

 

 

function requestCustomerInfo() {
 var sId = document.getElementById("txtCustomerId").value;
 top.frames["hiddenFrame"].location = "getcustomerdata.php?id=" + sId;
}

 


  該函數(shù)的第一步是從文本框中獲取客戶標(biāo)識(shí)號(hào)("txtCustomerId")。這是將文本框的ID txtCustomerId作為參數(shù),調(diào)用document.getElementById()函數(shù),并獲取返回的value屬性(value屬性保存了文本框中的文本內(nèi)容)來(lái)實(shí)現(xiàn)的。然后,將這個(gè)ID添加到字符串getcustomerdata.php?id=之后生成完整的URL。第二行代碼則是創(chuàng)建此URL并將其賦給隱藏幀。為了獲得對(duì)隱藏幀的引用,首先要使用top對(duì)象來(lái)獲取瀏覽器的頂級(jí)窗口(topmost window)。該對(duì)象擁有一個(gè)frames數(shù)組,在其中可以找到這個(gè)隱藏幀。由于每個(gè)幀都是一個(gè)窗口對(duì)象,因此可以將其位置設(shè)置為預(yù)期的URL。

  這是發(fā)出請(qǐng)求所需的所有信息。注意,由于這是一個(gè)GET請(qǐng)求(通過(guò)一個(gè)查詢字符串傳遞信息),因此是很簡(jiǎn)單的。(很快,你將看到如何使用隱藏幀技術(shù)來(lái)執(zhí)行一個(gè)POST請(qǐng)求。)除了requestCustomerInfo()函數(shù)之外,還需要另一個(gè)在查詢后顯示客戶信息的函數(shù)。當(dāng)數(shù)據(jù)返回時(shí),隱藏幀將調(diào)用這個(gè)displayCustomerInfo()函數(shù),其唯一的參數(shù)是包含要顯示的客戶數(shù)據(jù)的字符串:

 

 

function displayCustomerInfo(sText) {
 var divCustomerInfo = document.getElementById("divCustomerInfo");
 divCustomerInfo.innerHTML = sText;
}

 


  在這個(gè)函數(shù)中,第一行代碼將查詢對(duì)用于數(shù)據(jù)顯示的<div/>元素的引用。第二行代碼將把包含客戶信息的字符串(sText)的值賦給<div/>元素的innerHTML屬性。使用innerHTML屬性,可以將HTML嵌入到格式化的字符串中。這將由主顯示頁(yè)面的代碼來(lái)完成。現(xiàn)在我們將創(chuàng)建服務(wù)器端程序邏輯。getcustomerdata.php中的基本代碼是在基本的HTML頁(yè)面上添加兩處PHP代碼:

 

 

<html>
<head>
<title>Get Customer Data</title>
<?php
//php代碼
?>
</head>
<body>
<div id="divInfoToReturn"><?php echo sInfo ?></div>
</body>
</html>

 


  在該頁(yè)面中,第一個(gè)PHP代碼塊將包括查詢客戶數(shù)據(jù)的邏輯(很快將討論到)。而第二個(gè)PHP代碼塊則負(fù)責(zé)將包含客戶數(shù)據(jù)的sInfo變量的值輸出到<div/>元素中。從這個(gè)<div/>元素中,你可以讀取該數(shù)據(jù)并將數(shù)據(jù)傳送給顯示幀。為此,需要?jiǎng)?chuàng)建在頁(yè)面完全載入后調(diào)用的JavaScript函數(shù)。

 

 

window.onload = function () {
 var divInfoToReturn = document.getElementById("divInfoToReturn");
top.frames["displayFrame"].displayCustomerInfo(divInfoToReturn.innerHTML);
};

 


  該函數(shù)將直接賦給window.onload事件處理函數(shù)中。它首先獲取對(duì)包含客戶信息的<div/>元素的引用,然后使用數(shù)組top.frames訪問(wèn)顯示幀,并調(diào)用前面定義的display CustomerInfo()函數(shù),將其傳給<div/>元素的innerHTML屬性。這就是所有與發(fā)送該信息相關(guān)的JavaScript。但首先如何獲取這些信息呢?需要一些PHP代碼來(lái)從數(shù)據(jù)庫(kù)查詢信息。在PHP代碼中的第一步是定義所有需要的數(shù)據(jù)塊。在本例中,這些數(shù)據(jù)塊包括用來(lái)查詢的客戶ID、返回信息的sInfo變量,以及訪問(wèn)數(shù)據(jù)庫(kù)所需要的信息(數(shù)據(jù)庫(kù)服務(wù)器、數(shù)據(jù)庫(kù)名、用戶名、密碼以及SQL查詢字符串):

 

 

<?php
 sID = _GET["id"];
 sInfo = "";
 sDBServer = "your.databaser.server";
 sDBName = "your_db_name";
 sDBUsername = "your_db_username";
 sDBPassword = "your_db_password";
 sQuery = "Select * from Customers where CustomerId=".sID;

 //更多代碼
?>

 


  這段代碼首先從查詢字符串中獲取id參數(shù)。為了便于獲取,PHP將所有的查詢字符串參數(shù)組織于-GET數(shù)組中。這個(gè)id存儲(chǔ)在sID中,它將用來(lái)創(chuàng)建存儲(chǔ)于sQuery中的SQL查詢字符串。在此還將創(chuàng)建sInfo變量,并將其設(shè)置為空字符串。在這段代碼中的所有其他變量,都包含了指定特定數(shù)據(jù)庫(kù)配置的信息,根據(jù)你自己的實(shí)現(xiàn)環(huán)境將其替換為正確的值。獲取了用戶的輸入,做好了連接數(shù)據(jù)庫(kù)的基本準(zhǔn)備,下一步就是創(chuàng)建數(shù)據(jù)庫(kù)連接,執(zhí)行查詢,返回結(jié)果。如果存在一個(gè)指定ID的客戶,sInfo將填入包含所有數(shù)據(jù)的HTML字符串,包括對(duì)電子郵件地址創(chuàng)建一個(gè)鏈接,如果客戶ID是無(wú)效的,那么sInfo將填入錯(cuò)誤消息,以傳給顯示幀:

 

 

<?php
 sID = _GET["id"];
 sInfo = "";
 sDBServer = "your.databaser.server";
 sDBName = "your_db_name";
 sDBUsername = "your_db_username";
 sDBPassword = "your_db_password";
 sQuery = "Select * from Customers where CustomerId=".sID;
 oLink = mysql_connect(sDBServer,sDBUsername,sDBPassword);
 @mysql_select_db(sDBName) or sInfo="Unable to open database";

 if(oResult = mysql_query(sQuery) and mysql_num_rows(oResult) > 0) {
  aValues = mysql_fetch_array(oResult,MYSQL_ASSOC);
  sInfo = aValues['Name']."<br />".aValues['Address']."<br />".
aValues['City']."<br />".aValues['State']."<br />".
aValues['Zip']."<br /><br />Phone: ".aValues['Phone']."<br />".
"<a href=\"mailt".aValues['E-mail']."\">".
aValues['E-mail']."</a>";
 } else {
  sInfo = "Customer with ID sID doesn't exist.";
 }
 mysql_close(oLink);
?>

 


  突出顯示的頭兩行代碼用來(lái)完成從PHP到MySQL數(shù)據(jù)庫(kù)的連接。緊接著,調(diào)用mysql_ query()函數(shù)來(lái)執(zhí)行SQL查詢。如果函數(shù)返回結(jié)果,并且該結(jié)果至少包括一行,那么程序?qū)@取該信息,并將其存入變量sInfo中;否則,sInfo將填入一個(gè)錯(cuò)誤消息。最后兩行則負(fù)責(zé)釋放數(shù)據(jù)庫(kù)連接。

  關(guān)于更復(fù)雜的PHP和MySQL編程的闡述已超出了本文討論的范圍�,F(xiàn)在當(dāng)sInfo輸出到<div/>元素時(shí),它將包含正確的信息。onload事件處理函數(shù)將讀取這些數(shù)據(jù),然后將其發(fā)送到顯示幀上。如果查詢到客戶,其相應(yīng)的信息將會(huì)顯示出來(lái),如圖2-2所示。另一方面,如果客戶不存在,則會(huì)在屏幕的相同位置顯示錯(cuò)誤消息。無(wú)論如何,客戶服務(wù)代表都將獲得一個(gè)很好的用戶體驗(yàn)。你的第一個(gè)Ajax程序也就完成了。


圖 2-2

  3. 隱藏幀的POST請(qǐng)求

  前面的例子使用GET請(qǐng)求來(lái)從數(shù)據(jù)庫(kù)中獲取信息。由于客戶ID能夠以查詢字符串的形式添加到URL中,因此十分簡(jiǎn)單。但如果需要發(fā)送POST請(qǐng)求該怎么辦呢?它也可以使用隱藏幀技術(shù),不過(guò)需要一些額外的工作。POST請(qǐng)求通常是用于向服務(wù)器發(fā)送數(shù)據(jù)的場(chǎng)合,而與GET請(qǐng)求僅從服務(wù)器上獲取數(shù)據(jù)不同。盡管GET請(qǐng)求可以通過(guò)查詢字符串來(lái)向服務(wù)器發(fā)送額外的數(shù)據(jù),但一些瀏覽器最多只能夠處理512KB以內(nèi)的查詢字符串信息。對(duì)于POST請(qǐng)求而言,則可以發(fā)送2GB的信息,能夠良好地滿足絕大多數(shù)的應(yīng)用。

  從傳統(tǒng)意義上說(shuō),只能夠通過(guò)將表單的method屬性設(shè)置為post來(lái)發(fā)送POST請(qǐng)求。然后,包含在表單中的數(shù)據(jù)就會(huì)通過(guò)POST請(qǐng)求發(fā)送到action屬性中指定的URL上。更復(fù)雜的問(wèn)題是當(dāng)表單提交之后,將會(huì)從當(dāng)前頁(yè)跳轉(zhuǎn)到一個(gè)新的URL上,這與Ajax的目的是背道而馳的。但萬(wàn)幸的是,可以通過(guò)表單中一個(gè)不太知名的target屬性來(lái)簡(jiǎn)單實(shí)現(xiàn)。<form/>元素的target屬性的功能從某種意義上說(shuō)與<a/>元素的target屬性的功能類似:用來(lái)指定跳轉(zhuǎn)的目的URL。通過(guò)設(shè)置表單元素的target屬性,可以有效地使得在其他幀或窗口(在本例中是隱藏幀)中顯示出表單的提交結(jié)果之后,表單頁(yè)面仍然保持不變。首先重新定義一個(gè)幀集。與上一個(gè)例子唯一不同的是可見(jiàn)幀包含了用來(lái)輸入客戶數(shù)據(jù)的表單:

 

 

<frameset rows="100%,0" frameborder="0">
�。糵rame name="displayFrame" src="entry.htm" noresize="noresize" />
 <frame name="hiddenFrame" src="about:blank" noresize="noresize" />
</frameset>

 


  輸入表單的內(nèi)容包含在一個(gè)<form/>元素中,而且針對(duì)保存在數(shù)據(jù)庫(kù)中的每個(gè)字段都有一個(gè)相應(yīng)的文本框(除了自動(dòng)生成的客戶ID之外)。同樣也有一個(gè)<div/>元素,用來(lái)顯示與客戶端—服務(wù)器通信相關(guān)的狀態(tài)信息:

 

 

<form method="post" action="SaveCustomer.php" target="hiddenFrame">
<p>Enter customer information to be saved:</p>
<p>Customer Name: <input type="text" name="txtName" value="" /><br />
Address: <input type="text" name="txtAddress" value="" /><br />
City: <input type="text" name="txtCity" value="" /><br />
State: <input type="text" name="txtState" value="" /><br />
Zip Code: <input type="text" name="txtZipCode" value="" /><br />
Phone: <input type="text" name="txtPhone" value="" /><br />
E-mail: <input type="text" name="txtEmail" value="" /></p>
<p><input type="submit" value="Save Customer Info" /></p>
</form>
<div id="divStatus"></div>

 


  注意,<form/>元素的target屬性也設(shè)置為hiddenFrame,因此當(dāng)用戶點(diǎn)擊該按鈕時(shí),提交的結(jié)果將顯示在隱藏幀中。在本例中,主頁(yè)面中只需要一個(gè)JavaScript函數(shù):savaResult()。當(dāng)隱藏幀返回客戶數(shù)據(jù)保存結(jié)果時(shí),將調(diào)用該函數(shù):

 

 

function saveResult(sMessage) {
 var divStatus = document.getElementById("divStatus");
 divStatus.innerHTML = "Request completed: " + sMessage;
}

 


  隱藏幀的職責(zé)是向該函數(shù)傳遞一個(gè)消息,該消息將顯示給用戶。它可能是信息已保存的確認(rèn)信息,或者是說(shuō)明為什么保存失敗的錯(cuò)誤信息。接下來(lái)處理POST請(qǐng)求的文件是SavaCustomer.php。與前一個(gè)例子一樣,該頁(yè)面也是由簡(jiǎn)單的HTML頁(yè)面加上一些PHP和JavaScript代碼組成的。其中PHP代碼用來(lái)從請(qǐng)求中收集信息,然后將其保存到數(shù)據(jù)庫(kù)中。由于這是一個(gè)POST請(qǐng)求,因此_POST數(shù)組中包含了提交的所有信息:

 

 

<?php
 sName = _POST["txtName"];
 sAddress = _POST["txtAddress"];
 sCity = _POST["txtCity"];
 sState = _POST["txtState"];
 sZipCode = _POST["txtZipCode"];
 sPhone = _POST["txtPhone"];
 sEmail = _POST["txtEmail"];
 sStatus = "";

 sDBServer = "your.database.server";
 sDBName = "your_db_name";
 sDBUsername = "your_db_username";
 sDBPassword = "your_db_password";

 sSQL = "Insert into Customers(Name,Address,City,State,Zip,Phone,`E-mail`) ".
" values ('sName','sAddress','sCity','sState', 'sZipCode'".
", 'sPhone', 'sEmail')";

 //更多代碼
?>

 


  這個(gè)代碼片段將獲取與客戶相關(guān)的所有POST信息;此外,還定義了一個(gè)狀態(tài)消息(sStatus)以及所需的數(shù)據(jù)庫(kù)信息(與上一個(gè)例子相同)。這里的SQL語(yǔ)句是一個(gè)INSERT語(yǔ)句,它將獲取的信息添加到數(shù)據(jù)庫(kù)中。
執(zhí)行這個(gè)SQL語(yǔ)句的代碼與上一個(gè)例子十分類似:

 

 

<?php
 sName = _POST["txtName"];
 sAddress = _POST["txtAddress"];
 sCity = _POST["txtCity"];
 sState = _POST["txtState"];
 sZipCode = _POST["txtZipCode"];
 sPhone = _POST["txtPhone"];
 sEmail = _POST["txtEmail"];

 sStatus = "";
 sDBServer = "your.database.server";

 sDBName = "your_db_name";
 sDBUsername = "your_db_username";
 sDBPassword = "your_db_password";

 sSQL = "Insert into Customers(Name,Address,City,State,Zip,Phone,`E-mail`) ".
" values ('sName','sAddress','sCity','sState', 'sZipCode'".
", 'sPhone', 'sEmail')";

 oLink = mysql_connect(sDBServer,sDBUsername,sDBPassword);
 @mysql_select_db(sDBName) or sStatus = "Unable to open database";

 if(oResult = mysql_query(sSQL)) {
  sStatus = "Added customer; customer ID is ".mysql_insert_id();
 } else {
  sStatus = "An error occurred while inserting; customer not saved.";
 }

 mysql_close(oLink);
?>

 


  在此,mysql_query()函數(shù)的結(jié)果只是一個(gè)表示語(yǔ)句執(zhí)行成功的指示器。如果執(zhí)行成功, sStatus變量中將填入一個(gè)消息,表明保存已經(jīng)成功,并返回為該數(shù)據(jù)指定的客戶ID。mysql_ insert_id()函數(shù)始終返回在最新的INSERT語(yǔ)句返回值的基礎(chǔ)上自動(dòng)遞增的值。如果因?yàn)槟承┰颍撜Z(yǔ)句沒(méi)有成功執(zhí)行,sStatus變量將填入一個(gè)錯(cuò)誤消息。sStatus變量將輸出到一個(gè)在載入窗口時(shí)運(yùn)行的JavaScript函數(shù)中:

 

 

<script type="text/javascript">
 window.onload = function () {
  top.frames["displayFrame"].saveResult("<?php echo sStatus ?>");
 }
</script>

 


  這段代碼調(diào)用了savaResult()函數(shù),該函數(shù)定義于顯示幀中,傳入的參數(shù)值是PHP變量sStatus。由于該變量包含一個(gè)字符串,因此必須將PHP的echo語(yǔ)句放在引號(hào)中。當(dāng)執(zhí)行該函數(shù)時(shí),假設(shè)客戶數(shù)據(jù)已保存,則輸入表單頁(yè)面看起來(lái)如圖2-3所示。


圖 2-3

  當(dāng)執(zhí)行這段代碼之后,你還可以自由地使用同樣的表單向數(shù)據(jù)庫(kù)中添加更多客戶,因?yàn)樗辉傧А?/p>

  4. 隱藏iFrame

  新一代的客戶端—服務(wù)器通信模式幕后所采用的是iframe,它是在HTML 4.0中引入的。iframe與幀基本是相同的,唯一的區(qū)別是iframe可以放在一個(gè)未設(shè)置幀集的HTML頁(yè)面中,可以使頁(yè)面中的任意部分成為一個(gè)幀。iframe技術(shù)可以在未預(yù)先設(shè)置幀集的頁(yè)面中使用,能夠更好地適應(yīng)于功能的逐漸添加。iframe甚至還可以使用JavaScript在運(yùn)行時(shí)創(chuàng)建,為了簡(jiǎn)單起見(jiàn),語(yǔ)義化HTML(semantic HTML)支持使瀏覽器將Ajax功能看作是一個(gè)有益的增強(qiáng)(這將在稍后討論)。由于可以用與普通幀相同的方法使用和訪問(wèn)iframe,因此它們都是Ajax通信的理想選擇。發(fā)揮iframe的優(yōu)勢(shì)有兩種方法。最簡(jiǎn)單的方法是在頁(yè)面中簡(jiǎn)單地嵌入iframe,并像隱藏幀那樣用來(lái)發(fā)出請(qǐng)求。為此,第一個(gè)例子中的顯示頁(yè)面將修改為:

 

<p>Enter customer ID number to retrieve information:</p>
<p>Customer ID: <input type="text" id="txtCustomerId" value="" /></p>
<p><input type="button" value="Get Customer Info"
onclick="requestCustomerInfo()" /></p>
<div id="divCustomerInfo"></div>
<iframe src="about:blank" name="hiddenFrame" width="0" height="0"
frameborder="0"></iframe>

  注意,這個(gè)iframe中的width、height和frameborder屬性都設(shè)置成了0,這可將其從視線中隱去。由于iframe的名字仍是hiddenFrame,所以這個(gè)頁(yè)面的JavaScript代碼可以如前一樣正常工作。不過(guò),對(duì)于GetCustomerData.php頁(yè)面還需要做一些小的修改。在該頁(yè)面中的JavaScript函數(shù)先前是在名為displayFrame的幀中查找displayCustomerInfo()函數(shù)。如果你使用該技術(shù),又不存在該名字的幀,則必須修改代碼,用parent來(lái)代替它:

window.onload = function () {
 var divInfoToReturn = document.getElementById("divInfoToReturn");
 parent.displayCustomerInfo(divInfoToReturn.innerHTML);
};

  現(xiàn)在這個(gè)例子能夠和本文中的第一例子一樣正常工作了。

  第二種使用隱藏iframe的方法是通過(guò)JavaScript動(dòng)態(tài)地創(chuàng)建它們。由于并非所有瀏覽器實(shí)現(xiàn)iframe的方法都是一樣的,所以需要一些技巧,使得它有助于一步步地創(chuàng)建隱藏的iframe。

  第一步很簡(jiǎn)單,使用document.createElement()方法創(chuàng)建iframe并賦予必要的屬性:

function createIFrame() {
 var oIFrameElement = document.createElement("iframe");
 oIFrameElement.width=0;
 oIFrameElement.height=0;
 oIFrameElement.frameBorder=0;
 oIFrameElement.name = "hiddenFrame";
 oIFrameElement.id = "hiddenFrame";
 document.body.appendChild(oIFrameElement);

 //更多代碼
}

  本段代碼的最后一行很重要,因?yàn)樗鼘frame添加到document結(jié)構(gòu)中;沒(méi)有添加到document中的iframe是無(wú)法執(zhí)行請(qǐng)求的。另外注意,該iframe的name和id屬性都是設(shè)置為hiddenFrame。這是必要的,因?yàn)橛行g覽器是通過(guò)name屬性訪問(wèn)新的幀,而有些則是通過(guò)id屬性新的幀。緊接著定義一個(gè)全局變量,用來(lái)保存對(duì)該幀對(duì)象的引用。注意,針對(duì)iframe元素的這個(gè)幀對(duì)象并非是從createElement()函數(shù)返回的。要獲得該對(duì)象,必須從幀集合中獲取。以下就是即將保存在全局變量中的內(nèi)容:

var oIFrame = null;

function createIFrame() {
 var oIFrameElement = document.createElement("iframe");
 oIFrameElement.width=0;
 oIFrameElement.height=0;
 oIFrameElement.frameBorder=0;
 oIFrameElement.name = "hiddenFrame";
 oIFrameElement.id = "hiddenFrame";
 document.body.appendChild(oIFrameElement);

 oIFrame = frames["hiddenFrame"];
}

  如果你將這些代碼放到前面的iframe例子中,那么需要對(duì)requestCustomerInfo()函數(shù)進(jìn)行如下修改:

function requestCustomerInfo() {
 if (!oIFrame) {
  createIFrame();
  setTimeout(requestCustomerInfo, 10);
  return;
 }

 var sId = document.getElementById("txtCustomerId").value;
 oIFrame.location = "GetCustomerData.php?id=" + sId;
}

  基于這些修改,該函數(shù)將會(huì)檢查oIFrame是否為空。如果為空,則調(diào)用createFrame(),并會(huì)為該函數(shù)的調(diào)用設(shè)置10ms的超時(shí)時(shí)間。這是很必要的,因?yàn)橹挥蠭E瀏覽器能夠立即識(shí)別插入的iframe,大部分其他瀏覽器需要花幾毫秒來(lái)識(shí)別它,以允許通過(guò)它發(fā)送請(qǐng)求。當(dāng)再次執(zhí)行該函數(shù)時(shí),將執(zhí)行代碼的其余部分,其中最后一行已經(jīng)修改為對(duì)OIFrame對(duì)象的引用。盡管該技術(shù)能夠很容易地應(yīng)用于GET請(qǐng)求,但POST請(qǐng)求卻完全不同。只有一部分瀏覽器允許你設(shè)置表單的target屬性來(lái)動(dòng)態(tài)創(chuàng)建iframe;但I(xiàn)E并不是其中的一種。因此,要使用隱藏iframe技術(shù)來(lái)發(fā)送POST請(qǐng)求還需要一些技巧。

 

  5. 隱藏iframe的POST請(qǐng)求

  要使用隱藏iframe來(lái)完成POST請(qǐng)求,其方法是在隱藏幀中載入一個(gè)包含表單的頁(yè)面,用數(shù)據(jù)填充該表單,然后再提交該表單。當(dāng)這個(gè)可見(jiàn)的表單(你實(shí)際輸入數(shù)據(jù)的那個(gè))提交時(shí),必須取消這次提交而將信息轉(zhuǎn)發(fā)給隱藏幀。為此,必須定義一個(gè)函數(shù),用來(lái)處理iframe的創(chuàng)建以及隱藏表單的載入:

 

function checkIFrame() {
 if (!oIFrame) {
  createIFrame();
 }
 setTimeout(function () {
  oIFrame.location = "ProxyForm.htm";
 }, 10);
}

  這個(gè)名為checkIFrame()的函數(shù)首先檢查隱藏的iframe是否已經(jīng)創(chuàng)建。如果沒(méi)有,則調(diào)用createIFrame()。然后,在將iframe的地址設(shè)置為ProxyForm.htm(這是一個(gè)隱藏表單頁(yè)面)之前,為其設(shè)置一個(gè)超時(shí)值。由于該函數(shù)調(diào)用需要花一些時(shí)間,而重要的是該頁(yè)面每次加載時(shí)都將提交該表單。ProxyForm.htm文件很簡(jiǎn)單,只包括很少的JavaScript,用來(lái)提示主頁(yè)面已經(jīng)裝載完成:

<html>
<head>
<title>Proxy Form</title>
<script type="text/javascript">
 window.onload = function () {
  parent.formReady();
 }
</script>
</head>
<body>
<form method="post"></form>
</body>
</html>

  正如你所見(jiàn),該頁(yè)面的主體只包含一個(gè)空的表單,而標(biāo)題中只包含一個(gè)onload事件處理函數(shù)。當(dāng)載入該頁(yè)面時(shí),頁(yè)面將通過(guò)調(diào)用parent.formReady()來(lái)使主頁(yè)面知道它已經(jīng)做好接收請(qǐng)求的準(zhǔn)備。而formReady()函數(shù)則是包含在主頁(yè)面本身中的,類似于:

function formReady() {
 var oHiddenForm = oIFrame.document.forms[0];
 var oForm = document.forms[0];

 for (var i=0 ; i < oForm.elements.length; i++) {
  var oHidden = oIFrame.document.createElement("input");
  oHidden.type = "hidden";
  oHidden.name = oForm.elements[i].name;
  oHidden.value = oForm.elements[i].value;
  oHiddenForm.appendChild(oHidden);
 }
 oHiddenForm.action = oForm.action;
 oHiddenForm.submit();
};


  在該函數(shù)中的第一步是獲取對(duì)隱藏iframe中表單的引用,可以通過(guò)訪問(wèn)該幀的document.forms集合來(lái)獲取。由于在該頁(yè)面中只有一個(gè)表單,因此可以安全地從該集合中獲得第一個(gè)表單(即索引值為0),并將其存儲(chǔ)于oHiddenForm中。然后,將對(duì)主頁(yè)面表單的引用存于oForm中。緊接著,一個(gè)for循環(huán)對(duì)主頁(yè)面中該表單的各元素進(jìn)行遍歷(使用elements集合)。對(duì)于表單中的每一個(gè)元素,都將在隱藏幀(注意,必須使用oIFrame.document.createElement()而不只是document.createElement())中創(chuàng)建一個(gè)隱藏的輸入元素。這個(gè)隱藏的輸入元素?fù)碛信c該表單元素相同的名字和值,然后使用appendChild()函數(shù)將其添加到隱藏的表單中。

  當(dāng)所有的表單元素都添加完后,隱藏的表單還將設(shè)置與主頁(yè)面表單相同的action。通過(guò)從表單中讀取action來(lái)取代硬編碼,就可以在任何頁(yè)面中使用formReady()。該函數(shù)的最后一步是提交這個(gè)隱藏的表單。剩下的最后一件事就是確保主頁(yè)面的表單不以通常的方式提交自己。要達(dá)到這一目標(biāo),只需在onsubmit事件處理函數(shù)中調(diào)用checkIFrame()并返回false:

<form method="post" action="SaveCustomer.php"
onsubmit="checkIFrame();return false">

<p>Enter customer information to be saved:</p>
<p>Customer Name: <input type="text" name="txtName" value="" /><br />
Address: <input type="text" name="txtAddress" value="" /><br />
City: <input type="text" name="txtCity" value="" /><br />
State: <input type="text" name="txtState" value="" /><br />
Zip Code: <input type="text" name="txtZipCode" value="" /><br />
Phone: <input type="text" name="txtPhone" value="" /><br />
E-mail: <input type="text" name="txtEmail" value="" /></p>
<p><input type="submit" value="Save Customer Info" /></p>
</form>
<div id="divStatus"></div>


  通過(guò)以這種方式返回flase,可以阻止表單的默認(rèn)行為(將自己提交到服務(wù)器)。通過(guò)調(diào)用checkIFrame()方法來(lái)啟動(dòng)隱藏iframe中表單的提交進(jìn)程。當(dāng)這一任務(wù)完成后,就可以像使用隱藏幀POST請(qǐng)求的例子一樣使用本例;頁(yè)面SavaCustomer.php負(fù)責(zé)處理數(shù)據(jù),并當(dāng)完成時(shí)調(diào)用主頁(yè)面中的savaResult()函數(shù)。注意,本節(jié)中的例子是為了使其聚焦于與Ajax技術(shù)相關(guān)的問(wèn)題上,因而進(jìn)行了簡(jiǎn)化。如果在實(shí)際的Web應(yīng)用程序中使用,還需要提供更多的用戶反饋,諸如在發(fā)出請(qǐng)求時(shí)屏蔽該表單的輸入等。

  6. 隱藏幀技術(shù)的優(yōu)點(diǎn)和缺點(diǎn)

  現(xiàn)在,你已經(jīng)對(duì)使用隱藏幀所實(shí)現(xiàn)的強(qiáng)大功能有所了解了,我們將討論它的實(shí)用性。正如前面所說(shuō)的,該技術(shù)已經(jīng)存在多年,并且仍然在許多Ajax應(yīng)用中使用。使用隱藏幀的一個(gè)最大理由之一是它可以維護(hù)瀏覽器的歷史,使用戶仍然能夠使用瀏覽器上的后退和前進(jìn)按鈕。瀏覽器由于并不知道隱藏幀實(shí)際上被隱藏了,但對(duì)于其所發(fā)出的請(qǐng)求仍然是記錄在案的。然而,Ajax應(yīng)用程序的主頁(yè)面卻沒(méi)有修改,在隱藏幀中的修改意味著后退和前進(jìn)按鈕將依據(jù)該隱藏幀的訪問(wèn)歷史而非主頁(yè)面而變化。這也是為什么Gmail和Google Maps仍然使用該技術(shù)的理由。

  注意,iframe并非一直會(huì)存儲(chǔ)瀏覽器的歷史記錄。盡管IE始終會(huì)存儲(chǔ)iframe的歷史記錄,但Firefox只對(duì)使用HTML定義(也就是不包括使用JavaScript動(dòng)態(tài)創(chuàng)建)的iframe保存歷史記錄。Safari從不為iframe保存歷史記錄,不管它們是如何包含在該頁(yè)面中的。隱藏幀技術(shù)不利的一面是,對(duì)其背后發(fā)生的事了解甚少。它完全依賴于返回的正確頁(yè)面。本節(jié)的例子都存在相同的問(wèn)題:如果隱藏幀的頁(yè)面載入失敗,并不會(huì)向用戶提示出錯(cuò)消息;主頁(yè)面將繼續(xù)等待直到調(diào)用適當(dāng)?shù)腏avaScript函數(shù)。必須通過(guò)設(shè)置一個(gè)較長(zhǎng)周期(可能是5分鐘)的超時(shí)時(shí)間,然后如果頁(yè)面仍然沒(méi)有成功載入則顯示一條消息,以給用戶一個(gè)安慰。但這一切都只是一個(gè)變通方法,最主要的問(wèn)題是,對(duì)于后臺(tái)發(fā)生的HTTP請(qǐng)求缺乏充足的信息。幸運(yùn)的,我們還有其他選擇。

 

分享:淺談Ajax的缺點(diǎn)
在某網(wǎng)站瞎逛時(shí),發(fā)現(xiàn)這個(gè)鏈接,進(jìn)去逛了逛,覺(jué)得很有意思,大家也可以去看看,姑且不論你是否同意里面的觀點(diǎn),看看別人看待ajax的角度,這對(duì)于理解一個(gè)事物很有幫助。 下面是我對(duì)一部分缺陷的看法: 為Ajax而Ajax(Using Ajax for the sake of Ajax.) 很同意

來(lái)源:模板無(wú)憂//所屬分類:AJAX教程/更新時(shí)間:2010-03-23
相關(guān)AJAX教程