一起草最新网址_日韩一区二区麻豆国产_91视频婷婷_日本一区二区视频在线_日韩激情一区二区三区_国产另类第一区_成人免费在线播放视频_亚洲永久精品ww.7491进入_久久这里有精品视频_久久精品一级片_日韩av在线网页_波多野结衣不卡视频

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

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

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

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

  隱藏幀技術(shù)

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

  1. 模式

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

圖 2-1

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

  2. 隱藏幀的GET請求

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

  首先,在實現(xiàn)客戶資料查詢之前,你必須有一個包含該信息的數(shù)據(jù)庫表。可以使用以下SQL腳本來創(chuàng)建一個客戶表:


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

 

 

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

 


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

 

 

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

 


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

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

 

 

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

 


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

 

 

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

 


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

 

 

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

 


  該函數(shù)將直接賦給window.onload事件處理函數(shù)中。它首先獲取對包含客戶信息的<div/>元素的引用,然后使用數(shù)組top.frames訪問顯示幀,并調(diào)用前面定義的display CustomerInfo()函數(shù),將其傳給<div/>元素的innerHTML屬性。這就是所有與發(fā)送該信息相關(guān)的JavaScript。但首先如何獲取這些信息呢?需要一些PHP代碼來從數(shù)據(jù)庫查詢信息。在PHP代碼中的第一步是定義所有需要的數(shù)據(jù)塊。在本例中,這些數(shù)據(jù)塊包括用來查詢的客戶ID、返回信息的sInfo變量,以及訪問數(shù)據(jù)庫所需要的信息(數(shù)據(jù)庫服務(wù)器、數(shù)據(jù)庫名、用戶名、密碼以及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ù)組中。這個id存儲在sID中,它將用來創(chuàng)建存儲于sQuery中的SQL查詢字符串。在此還將創(chuàng)建sInfo變量,并將其設(shè)置為空字符串。在這段代碼中的所有其他變量,都包含了指定特定數(shù)據(jù)庫配置的信息,根據(jù)你自己的實現(xiàn)環(huán)境將其替換為正確的值。獲取了用戶的輸入,做好了連接數(shù)據(jù)庫的基本準(zhǔn)備,下一步就是創(chuàng)建數(shù)據(jù)庫連接,執(zhí)行查詢,返回結(jié)果。如果存在一個指定ID的客戶,sInfo將填入包含所有數(shù)據(jù)的HTML字符串,包括對電子郵件地址創(chuàng)建一個鏈接,如果客戶ID是無效的,那么sInfo將填入錯誤消息,以傳給顯示幀:

 

 

<?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);
?>

 


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

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


圖 2-2

  3. 隱藏幀的POST請求

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

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

 

 

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

 


  輸入表單的內(nèi)容包含在一個<form/>元素中,而且針對保存在數(shù)據(jù)庫中的每個字段都有一個相應(yīng)的文本框(除了自動生成的客戶ID之外)。同樣也有一個<div/>元素,用來顯示與客戶端—服務(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)用戶點擊該按鈕時,提交的結(jié)果將顯示在隱藏幀中。在本例中,主頁面中只需要一個JavaScript函數(shù):savaResult()。當(dāng)隱藏幀返回客戶數(shù)據(jù)保存結(jié)果時,將調(diào)用該函數(shù):

 

 

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

 


  隱藏幀的職責(zé)是向該函數(shù)傳遞一個消息,該消息將顯示給用戶。它可能是信息已保存的確認(rèn)信息,或者是說明為什么保存失敗的錯誤信息。接下來處理POST請求的文件是SavaCustomer.php。與前一個例子一樣,該頁面也是由簡單的HTML頁面加上一些PHP和JavaScript代碼組成的。其中PHP代碼用來從請求中收集信息,然后將其保存到數(shù)據(jù)庫中。由于這是一個POST請求,因此_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')";

 //更多代碼
?>

 


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

 

 

<?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é)果只是一個表示語句執(zhí)行成功的指示器。如果執(zhí)行成功, sStatus變量中將填入一個消息,表明保存已經(jīng)成功,并返回為該數(shù)據(jù)指定的客戶ID。mysql_ insert_id()函數(shù)始終返回在最新的INSERT語句返回值的基礎(chǔ)上自動遞增的值。如果因為某些原因,該語句沒有成功執(zhí)行,sStatus變量將填入一個錯誤消息。sStatus變量將輸出到一個在載入窗口時運行的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。由于該變量包含一個字符串,因此必須將PHP的echo語句放在引號中。當(dāng)執(zhí)行該函數(shù)時,假設(shè)客戶數(shù)據(jù)已保存,則輸入表單頁面看起來如圖2-3所示。


圖 2-3

  當(dāng)執(zhí)行這段代碼之后,你還可以自由地使用同樣的表單向數(shù)據(jù)庫中添加更多客戶,因為它不再消失。

  4. 隱藏iFrame

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

 

<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>

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

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

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

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

  第一步很簡單,使用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);

 //更多代碼
}

  本段代碼的最后一行很重要,因為它將iframe添加到document結(jié)構(gòu)中;沒有添加到document中的iframe是無法執(zhí)行請求的。另外注意,該iframe的name和id屬性都是設(shè)置為hiddenFrame。這是必要的,因為有些瀏覽器是通過name屬性訪問新的幀,而有些則是通過id屬性新的幀。緊接著定義一個全局變量,用來保存對該幀對象的引用。注意,針對iframe元素的這個幀對象并非是從createElement()函數(shù)返回的。要獲得該對象,必須從幀集合中獲取。以下就是即將保存在全局變量中的內(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例子中,那么需要對requestCustomerInfo()函數(shù)進行如下修改:

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

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

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

 

  5. 隱藏iframe的POST請求

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

 

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

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

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

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

  當(dāng)所有的表單元素都添加完后,隱藏的表單還將設(shè)置與主頁面表單相同的action。通過從表單中讀取action來取代硬編碼,就可以在任何頁面中使用formReady()。該函數(shù)的最后一步是提交這個隱藏的表單。剩下的最后一件事就是確保主頁面的表單不以通常的方式提交自己。要達(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>


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

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

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

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

 

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

來源:模板無憂//所屬分類:AJAX教程/更新時間:2010-03-23
相關(guān)AJAX教程
久久久久在线| 日韩在线视频免费播放| 亚洲三级av在线| 五月天综合激情| 欧亚精品在线观看| 欧美a级一区二区| 中文视频一区视频二区视频三区 | 亚洲激情欧美激情| 制服下的诱惑暮生| 亚洲男女自偷自拍图片另类| 国产一级片一区二区| 91九色偷拍| 久久久精品免费观看| 亚洲欧美国产中文| 亚洲第一区中文99精品| 国产精品成人久久久| av成人观看| 国产精品蜜臀av| 日韩少妇一区二区| 色偷偷偷亚洲综合网另类| 国产一区二区在线视频观看| 免费日韩电影在线观看| 一区二区三区欧美视频| 人妻少妇无码精品视频区| 九九久久综合网站| 久久国产精品色| 国产欧美在线一区| 亚洲国产中文字幕在线观看| 国产又粗又猛又爽又黄视频 | 高清在线不卡av| 毛片在线播放视频| 日韩欧美一区在线观看| 欧美性受xxx黑人xyx性爽| 裸模一区二区三区免费| 天天操天天综合网| 国产精品 欧美 日韩| 91精品啪aⅴ在线观看国产| 国产网红主播福利一区二区| 亚洲第一黄色网址| 久久免费福利视频| 成人福利视频网站| 91精品又粗又猛又爽| 久久久久久国产精品久久| 国产99一区视频免费| 免费欧美一级片| 欧美日韩成人黄色| 99久久精品免费看国产免费软件| 美国黄色一级视频| 91av中文字幕| 国产日韩av一区| 日本二区三区视频| 国产精品12| 欧美视频一二三| 国产又大又粗又爽| 一区二区欧美日韩| 精品久久久久久无| 久久这里有精品15一区二区三区| 一级黄色香蕉视频| 破处女黄色一级片| 国产不卡一区二区在线观看| 国产又黄又爽又色| www男人的天堂| 亚洲激情啪啪| 国产男女无遮挡| 日本三级免费网站| 久久综合色视频| 国产嫩草一区二区三区在线观看 | 国产精品伦理在线| 日韩女优在线观看| 久久这里只精品| 日本高清一区| 国产精品初高中精品久久| 夜夜爽99久久国产综合精品女不卡| 国产精品国产精品国产专区蜜臀ah | 欧美熟妇精品一区二区| 亚洲精品20p| av av在线| 亚洲妇女无套内射精| 九九九久久久久久久| 在线视频日韩欧美| 奇米视频888| 日本a视频在线观看| 亚洲国产日韩欧美| 91精品国产免费久久综合| 日韩中文欧美在线| 老牛影视av老牛影视av| 亚洲成人第一| 欧美日韩精品福利| 成a人片国产精品| 久久激情一区| 十八禁一区二区三区| 高清一区二区三区四区| 一区二区三区精品久久久| 美日韩在线视频| 一区二区三区四区欧美| 在线观看欧美一区二区| 无码人妻aⅴ一区二区三区69岛| 欧美一区免费观看| 精品人妻伦九区久久aaa片| 免费在线观看a视频| 欧美亚洲日本在线| 黄色一级片在线看| 99热一区二区三区| 免费看a级黄色片| 日韩精品一区二区三| 国产精品夜夜夜爽阿娇| 日本一区二区三区四区五区| 国产成人免费看一级大黄| 亚洲毛片亚洲毛片亚洲毛片| 午夜视频在线观看国产| 久久久久久九九九九九| 国产黄色av片| 在线视频亚洲一区| 久久99欧美| 久久免费视频99| 久久九九国产精品| 欧美日本精品一区二区三区| 欧美中文字幕一区| 精品电影一区二区| 国产精品一区二区果冻传媒| 男人天堂av在线播放| 中文字幕精品一区二区精| 小日子的在线观看免费第8集| 在线播放 亚洲| 国产欧美日韩视频一区二区三区| 国内免费久久久久久久久久久| 91入口在线观看| www一区二区www免费| 亚洲精品在线网址| 在线观看中文字幕视频| 国产精品 日产精品 欧美精品| 亚洲人高潮女人毛茸茸| www.日本xxxx| 热久久国产精品| 色8久久精品久久久久久蜜| 91精品国产精品| 第九区2中文字幕| 欧美色图另类小说| 国产视频不卡在线| 中文字幕 国产| 久久这里只有精品6| 国产一区二区影院| 亚洲人成人一区二区在线观看 | 亚洲午夜精品久久久久久浪潮| 欧美a级免费视频| 国产wwwxx| 欧美s码亚洲码精品m码| 欧美极品aaaaabbbbb| 国产超碰在线一区| 97在线看福利| 波多野结衣不卡视频| 亚洲午夜国产一区99re久久| 91人成网站www| 国产亚洲二区| 久久99精品久久久久久三级| 青青在线视频免费观看| 久久久九九九热| 亚洲av无码精品一区二区| www.在线欧美| 欧美成人激情免费网| 69堂成人精品免费视频| 欧美不卡在线视频| 日韩av在线最新| 久久精品成人动漫| 成人国产亚洲精品a区天堂华泰| 韩国三级与黑人| 中文在线字幕av| 成人18精品视频| 日韩成人在线免费观看| 日韩中文字幕在线视频观看| 国产精品996| 国产日韩欧美影视| 亚洲黄色精品视频| 久久成人这里只有精品| 一级黄色特级片| 可以看av的网站久久看| 亚洲国产日日夜夜| 中文字幕精品久久| 亚洲欧美日韩不卡一区二区三区| 一本色道综合久久欧美日韩精品| 国产99视频在线| 日韩在线一区二区| 中文字幕日韩一区二区| 欧美另类变人与禽xxxxx| 亚洲午夜精品久久久久久久久久久久| 国产中文日韩欧美| 久久精品免费在线| 日韩欧美精品中文字幕| 欧美国产日韩二区| 日本不卡一区二区在线观看| 久88久久88久久久| 国产伦精品一区二区三区视频黑人| 最近中文字幕免费观看| 尤物精品国产第一福利三区| 涩多多在线观看| 欧美韩国日本不卡| 日本精品一区二区三区在线播放视频| 免费视频爱爱太爽了| 国产在线拍揄自揄拍无码视频| 亚洲午夜精品网| 国产欧美精品一区二区三区-老狼 国产欧美精品一区二区三区介绍 国产欧美精品一区二区 | 国产口爆吞精一区二区| 91在线精品一区二区三区| 欧美精品日韩综合在线| 国产精品免费区二区三区观看 | 日韩成人av影视| 日韩欧美卡一卡二| www.国产二区| 97人妻精品一区二区三区动漫| 色综合91久久精品中文字幕| 亚洲精品毛片一区二区三区| 日本中文字幕成人| 中文天堂在线视频| 国产精品久久久久久久美男| 日本黄色片免费观看| 一区二区三区高清| 国产精品久久久久久久久借妻| 国产这里有精品| 亚洲精品乱码久久久久久黑人| 欧美性xxxx69| 国产一线在线观看| 亚洲区小说区图片区| 91国产视频在线观看| 好吊操视频这里只有精品| 国产午夜亚洲精品羞羞网站| 国产日产久久高清欧美一区| 国产少妇在线观看| 欧美一卡2卡三卡4卡5免费| 国产精品嫩草视频| 五月天免费网站| 精品精品国产高清a毛片牛牛| 东北少妇不带套对白| 国产福利91精品| 日本最新高清不卡中文字幕| 毛片aaaaaa| 波多野结衣中文字幕一区| 久久久久久久97| 成人免费看aa片| 亚洲欧美一区二区不卡| 日本韩国欧美精品大片卡二| 亚洲精品无码一区二区| 国产精品久久久久毛片软件| 中文字幕欧美人妻精品一区| www.激情成人| 免费国产一区| 成人小视频在线| 欧美二级三级| 在线视频这里只有精品| 亚洲加勒比久久88色综合| 黄色在线免费播放| 91福利视频久久久久| 免费日韩在线视频| 91中文在线观看| 中文字幕免费在线观看视频一区| 美女少妇一区二区| 6080yy午夜一二三区久久| 最近中文字幕无免费| 欧美性猛交xxxx乱大交蜜桃| www亚洲国产| 99视频一区二区| 亚洲一区二区三区成人在线视频精品 | 中文字幕精品在线视频| 国产精品久久久久久69| 九九九九久久久久| 337p粉嫩色噜噜噜大肥臀| 色噜噜狠狠狠综合曰曰曰| 特级做a爱片免费69| 久久久最新网址| 久久一区二区电影| 国产一区二区三区四区在线观看| www久久99| 91麻豆6部合集magnet| 黄色av电影网站| 日韩免费av片在线观看| 97se亚洲国产综合自在线观| 一级特级黄色片| 欧美亚洲在线观看| 91在线免费播放| 色婷婷777777仙踪林| 亚洲国产成人私人影院tom| 黄色三级中文字幕| 国产精品丝袜久久久久久app| 视频在线观看免费高清| 欧美精品乱码久久久久久按摩| 加勒比精品视频| 亚洲欧美另类图片小说| 美女日批免费视频| 国产成人午夜高潮毛片| 亚洲av成人精品一区二区三区| 欧美国产日韩xxxxx| 手机看片福利永久| 久久久久资源| 中文字幕一区二区视频| 亚洲天堂一区二区在线观看| 亚洲国产中文字幕久久网| 成人精品视频在线播放| 欧美色图片你懂的| 色欲狠狠躁天天躁无码中文字幕| 欧美伦理91i| 天堂在线亚洲视频| 污片在线免费看| 国产亚洲精品91在线| 国产乱国产乱老熟| 国产精品一区二区久久精品 | 亚洲男女毛片无遮挡| 欧美女同在线观看| 黄色一区二区在线| 88av在线播放| 日韩美女在线视频| 国产不卡精品视频| 777久久精品一区二区三区无码| 在线免费观看日韩欧美| 欧美亚洲日本在线| 国产区亚洲区欧美区| 天天操天天干天天舔| 国产精品久久久久久久久粉嫩av| 久久亚洲精精品中文字幕早川悠里 | 欧美刺激性大交免费视频| 国产精品久久免费| 人妻av无码专区| 欧美丰满少妇xxxx| 午夜久久久影院| www.国产精品视频| 国产视频精品视频| 成人免费在线一区二区三区| 在线影院国内精品| 免费观看30秒视频久久| 精品成人av一区二区三区| 91国内免费在线视频| 欧美韩日一区二区三区| 久久丫精品国产亚洲av不卡| 欧美亚洲一区在线| 成人午夜精品在线| 韩国黄色一级片| 91亚洲永久免费精品| 中文字幕一区二区三区在线不卡| 一区二区成人网| 日韩精品在线观| 一级做a爱片久久毛片| 日本人视频jizz页码69| 成人激情视频免费在线| 666欧美在线视频| 中文字幕精品一区二| 青青草精品视频在线| 久久久国产精品视频| www.欧美日韩| 免费成人在线视频网站| 亚洲美女av电影| 欧美国产亚洲另类动漫| 9i看片成人免费看片| 人人妻人人澡人人爽精品欧美一区| 性色av一区二区三区| 欧美一级黄色大片| 国产精品的网站| 蜜桃精品视频在线| 久久久精品一区二区涩爱| 999久久久精品视频| 欧美日韩亚洲一区二区三区在线观看 | 精品久久久久久久中文字幕| 国产模特av私拍大尺度| 久久久久久www| 欧美蜜桃一区二区三区| 免费成人你懂的| 色综合网色综合| 国产熟妇搡bbbb搡bbbb| 一区二区在线观| 久久精品国产69国产精品亚洲| 亚洲欧美另类综合偷拍| 亚洲精品喷潮一区二区三区| 国产ts丝袜人妖系列视频| 99re视频在线播放| 亚洲最大成人综合| 色噜噜在线播放| 国产精品无码一区二区三区| 久久久久久久久久久久久久一区| 一本一道久久a久久精品逆3p| 欧美一区二区黄| 亚洲二区在线观看| 极品少妇xxxx偷拍精品少妇| 亚洲精品一区二区三区四区| 亚洲天堂一区在线| 91动漫免费网站| 特级丰满少妇一级| 韩国成人av| 日韩中文字幕国产| 亚洲美女偷拍久久| 日韩 欧美一区二区三区| 亚洲精品在线视频播放| 一本久久a久久精品vr综合| 欧美激情啊啊啊| 日韩欧美的一区二区| 亚洲欧美日韩国产一区二区三区 | 69av在线视频| 精品成人久久av| 国产精品麻豆久久久| 免费人成在线不卡| 中文字幕手机在线视频| 国产成人av免费观看| 日韩国产欧美一区| 成人网页在线免费观看| 国产亚洲一区二区在线| 97se亚洲国产综合自在线观| 中文字幕在线有码| 免费看污污网站| 欧美性xxxx69| 不卡的av一区| 亚洲mm色国产网站| 国产精选一区二区| 成人国产精品久久久| 国产精品日韩欧美|