原生Ajax講解

典型的http通信:瀏覽器向服務器發出請求,服務器向客戶端返回響應,瀏覽器重新加載頁面,這種不連續的頁面加載方式導致用戶的體驗變得雜亂,缺乏連貫性。

如:

在一般的web應用程序中,用戶填寫表單字段然后單擊submit按鈕,然后整個表單發送到服務器,服務器將它轉發給處理該表單的腳本(PHP或JAVA),腳本執行完成后再發送回全新的頁面。該頁面返回的可能是帶有已經填充某些數據的新表單的html,也可能返回的是一個確認頁面。在服務器上的腳本處理該表單時和返回新頁面的這段時間里,用戶必須等待且屏幕是一片空白,等到服務器返回數據后再重新繪制出頁面。

ajax,用戶在填寫表單時,數據就會發送給一些javascript代碼而不是直接發送給服務器。javascript代碼捕獲表單數據并向服務器發送請求。此時,用戶屏幕上的表單不會閃爍,消失或延遲。用戶不用等待服務器的響應就可以繼續輸入數據,滾動屏幕和繼續使用頁面。然后,服務器將數據返回給javascript代碼(仍然在web表單中),javascript代碼決定如何處理這些數據。它可以迅速更新表單數據,讓人感覺應用程序是立即完成的,表單沒有提交或刷新而用戶就得到了新數據。javascript甚至可以對收到的數據執行一些操作然后再發送另一個請求,完全不需要用戶干預。這就是ajax的強大之處,它可以根據需要自行與服務器進行交互,用戶甚至不知道幕后所發生的一切。



Ajax允許客戶端javascript向服務器請求和接收數據,而無須刷新頁面。這種技術允許開發人員創建不中斷的應用程序,用新數據重載頁面的某些部分。

Ajax表示使用javascript收發來自web服務器的數據,且無須重載整個頁面(僅刷新頁面的局部)的模式------在形式和功能上模擬桌面應用程序。

就目前而言,編寫應用程序時有兩種基本的選擇:

  1. 桌面應用程序
  2. WEB應用程序

桌面應用程序通常從其他網站下載,安裝到您的計算機上。桌面應用程序可能使用互聯網下載更新,但運行這些應用程序的代碼在您的桌面計算機上。

WEB應用程序運行在互聯網的某臺WEB服務器上,要通過WEB瀏覽器訪問這種應用程序。

桌面應用程序一般很快,就在您的計算機上運行,不用等待互聯網的鏈接;web應用程序提供了在桌面上不能實現的服務(比如天貓,淘寶這種具有支付功能的網站),但是,隨著web的強大而出現的是等待,等待服務器的響應,等待屏幕的刷新和等待請求返回和生成新的頁面。


XMLHttpRequest的一個優點在于它易于使用,我們只需創建對象,發送請求,等待服務器的響應即可。

ajax是由html,javascript技術,DHTML和DOM組成。

應用Ajax的例子

QQ空間:

你不停的拉滾動條,動態就一直在更新內容,頁面沒有刷新。

百度搜索:

你開始輸入數據時,一個下拉框就會顯示你可能干興趣的與搜索關鍵字相關的條目。



瀏覽器支持:

IE5+

FF1+

Opera9+

Safari2+

Chrome1+


創建XMLHttpRequest對象

所有瀏覽器都有javascript對象XMLHttpRequest。

XMLHttpRequest對象起源于一個Microsoft組件XmlHttp,組件在庫MSXML(Active XML解析器)中隨IE5發布,該組件為開發人員提供了一種打開HTTP連接并檢索XML數據的簡單方法。盡管XMLHttpRequest對象名稱包含有XML,但可以使用它獲取其他類型的數據。


跨瀏覽器問題:

瀏覽器對XMLHttpRequest對象的支持分兩種,ActiveX(ie5/6)和內置支持(其他瀏覽器)。這兩類瀏覽器僅在創建XMLHttpRequest對象時有區別,在創建后,其余的代碼則兼容各種瀏覽器。

第一類:使用ActiveX(IE5/6)

因為XMLHttpRequest對象來源于庫MSXML(Active XML解析器),所以在這些瀏覽器中實例化XMLHttpRequest對象,就需要創建一個ActiveX對象。

var myhttp=new ActiveXObject("Microsoft.XMLHttp");


這行代碼創建Microsoft的XMLHttpRequest對象的第一個版本。Microsoft的XmlHttp對象還有其他許多的版本。后面的例子將給出使用最新版本的方式。


第二類:調用內置的構造函數(IE7+,其他瀏覽器)

var myhttp=new XMLHttpRequest();


這行代碼創建的XMLHttpRequest對象沒有不同的版本,只需調用構造函數,就能創建和使用XMLHttpRequest對象。


?兼容:一個函數創建適用于所有的瀏覽器的對象。

function createXmlHttpRequest(){if (window.XMLHttpRequest) {var oHttp = new XMLHttpRequest();return oHttp;} else if (window.ActiveXObject) {var versions = ["MSXML2.XmlHttp.6.0","MSXML2.XmlHttp.3.0"];for (var i = 0; i < versions.length; i++) {try {oHttp = new ActiveXObject(versions[i]);return oHttp;} catch (error) {//do nothing here}}}return null;
}


首先檢查是否存在window.XMLHttpRequest,如果存在,函數即使用XMLHttpRequest構造函數來創建XMLHttpRequest對象(函數遇到return語句退出函數不再執行函數后面的代碼)。否則,就檢測用于ie5/6的window.ActiveXObject,并嘗試用最新的XmlHttp版本創建對象。如果所有的情況都不能創建XMLHttpRequest對象,那么就返回null。

注意:測試順序很重要。先測試window.XMLHttpRequest對象,是因為ie7支持window.XMLHttpRequest和window.ActiveXObject。


使用XMLHttpRequest對象

一旦創建了XMLHttpRequest對象,就可以準備用它來請求數據。該對象提供的方法和屬性,都與發送請求及處理響應有關。XMLHttpRequest對象唯一的目的就是讓您發送請求和接收響應,其他一切都是javascript,css或者頁面中的其他代碼的工作:改變用戶界面,切換對象,解析服務器返回的數據。


第一步,open()方法

?初始化該XMLHttpRequest對象,接受三個參數:

myHttp.open(requestType,url,boolean)

第一個requestType表示請求類型的字符串,其值可以是GET或者POST.
第二個參數是要作為請求發送目標的URL。
第三個參數是true或false,表示請求是以異步還是同步的模式發出。
  • false同步模式發出的請求會暫停所有javascript代碼的執行,知道服務器獲得響應為止,如果瀏覽器在連接網絡時或者在下載文件時出了故障,頁面就會一直掛起。?
  • true:異步模式發出的請求,請求對象收發數據的同時,瀏覽器可以繼續加載頁面,執行其他javascript代碼。
myHttp.open("GET","http://localhost/myfile.txt",false);


注意:首選異步。
?

第二步,send()方法:

使用該方法發送請求。只接受一個參數,參數是一個字符串,包含隨請求一起發送的請求體。GET請求不包含任何信息,所以把null傳送為參數(GET請求把要發送給服務器的數據寫在請求url中,所以send()中不需要發送任何數據。)。

var myHttp=createXmlHttpRequest();
myHttp.open("GET","http://localhost/myfile.txt",false);
myHttp.send(null);

這段代碼發出一個GET請求,以同步模式獲取myfile.txt文件。調用send()方法會把該請求發送給服務器。

雖然可以使用send()發送數據,但也能通過URL本身發送數據。事實上,GET請求(在ajax應用中占80%)中,用URL發送數據要容易的多。如果要發送安全信息或XML,可以考慮send()發送內容。如果不需要send()傳遞數據,則只要傳遞null作為該方法的參數即可。

注意send()方法必須接收一個參數,甚至可以是null。


status屬性:

如果服務器響應請求并完成了處理但是報告了一個錯誤怎么辦?不管是頁面不存在404,或者訪問數據收到保護404或禁止訪問401.無論哪種情況,這些錯誤碼都是從完成的響應中得到的。換句話說,服務器履行了請求(http就緒狀態是4)但是沒有返回客戶機預期的數據。

每個XMLHttpRequest對象獨有status屬性,該屬性包含了與服務器的響應一起發送回來的http狀態碼。服務器返回狀態碼200表示請求成功,404表示找不到請求的文件。


var myHttp=createXmlHttpRequest();myHttp.open("GET","http://localhost/myfile.txt",false);myHttp.send(null);if(myHttp.status==200){alert("############");}else if(myHttp.status==404){alert("$$$$$$$$$$$$$$$");}else{alert(myHttp.status);}


這段代碼通過檢查status屬性,確定給用戶顯示什么信息。如果返回的狀態碼為200即表示存在請求文件,404則請求文件不存在。

HTTP狀態碼有很多,因此不可能檢查每個狀態碼,大多數情況下,我們只需要關心請求是否成功即可(狀態碼200)。

精簡代碼:

var myHttp=createXmlHttpRequest();myHttp.open("GET","http://localhost/myfile.txt",false);myHttp.send(null);if(myHttp.status==200){alert("success");}else{alert("error"+myHttp.status);}


http狀態碼

從web出現以來,它們就已經存在了。在web瀏覽器中您可能經常看到過這幾個狀態碼:
  • 401:未經授權
  • 403:禁止訪問
  • 404:沒有找到網頁
在很多ajax應用程序中,您將看到一個回掉函數,它負責檢查就緒狀態,然后繼續利用從服務器響應中返回的數據。但是種做法往往是不可取的會帶來一些問題。比如,服務器腳本需要認證,而請求沒有提供有效的證書,那么服務器就會返回403或401之類的錯誤代碼,然而這時,由于服務器已經對請求做了應答,因此就緒狀態就被設置了4(即使應答不是請求所期望的)。最終,用戶沒有獲得有效的數據,當javascript試圖使用不存在的服務器數據時就可能會出現錯誤。


異步請求

http就緒狀態

前面事例演示了同步請求的簡潔性,而異步請求會給代碼添加一些復雜性。因為異步請求必須處理readystatechange事件。在異步請求中,XMLHttpRequest對象提供了readyState屬性,該屬性包含一個數值,每個值都代表請求生存期中的特定狀態(http就緒狀態)。如:

  • 0:已經創建對象,但還沒有調用open()方法。
  • 1:已經調用open()方法,但還沒有發送請求。
  • 2:請求已經發送,標題和狀態已經收到,并可用。
  • 3:接收到來自服務器的響應。
  • 4:接收完請求數據,表示已經完成請求。

與大多數瀏覽器兼容問題一樣,這些狀態的使用都不一致。也許你期望值是從0,1,2,3,4變化的,但實際上,一些瀏覽器從不報告0或者1而直接從2開始,然后3和4.還有一些瀏覽器則報告所有的狀態,0,1,2,3,4.還有一些則多次報告1.

IE7+:1,2,3,4 。沒有0。
其他瀏覽器:2,3,4 。沒有0和1。

就緒狀態中的readyState屬性為0,表示的是未初始化狀態。一旦對請求對象調用open()之后,這個屬性就被設置為1.由于您通常都是在一對請求進行初始化之后就立即調用open()。因此很少會看到readyState==0的狀態。另外,未初始化的就緒狀態在實際的應用程序中是沒有真正的用處的。
要看到readyState==0的狀態就必須在調傭open()之前查看就緒狀態。

正在處理的請求的就緒狀態,除了0就緒狀態之外,請求對象還需要依次經歷典型的請求和響應的其他幾個鐘就緒狀態,最后才以就緒狀態4的形式結束(確保了服務器已經完成對請求的處理)。


注意:當0等于4時,相同的XMLHttpRequest對象使用在多個函數之間生成多個請求時候。
當多個javascript函數都使用相同的請求對象時,你需要檢查就緒狀態0來確保這個請求對象沒有正在使用。由于readyState==4表示一個已完成的請求,因此您經常會發現那些目前沒有在使用的處于就緒狀態的請求對象仍然被設置成了4-----這是因為從服務器返回來的數據已經使用過了。但是從他們被設置為4之后就沒有進行任何變化。有一個函數abort()會重新設置請求對象,但是這個函數卻不是真正為了這個目的而使用的。如果你必須使用多個函數,最好是為每個函數都創建對象并使用一個函數,而不是在多個函數之間共享相同的對象。




每當readyState屬性發生變化時,都會觸發readystatechange事件,調用onreadystatechange事件處理程序。

onreadystatechange允許指定一個回調函數,回調函數允許服務器反向調用web頁面中的代碼。當服務器完成請求之后,會查看XMLHttpRequest對象,特別是onreadystatechange屬性,然后調用該屬性指定的任何方法,無論網頁本身在做什么。這就稱為異步的原因,用戶在操作頁面,而服務器在響應請求并觸發onreadystatechange屬性指定的回調方法。
前面提到的當服務器完成請求之后會在XMLHttpReques的onreadystatechange屬性中查找要調用的方法。這是真的,但這說的不完整。事實上,每當http就緒狀態改變(readyState屬性發生變化)時服務器都會調用該方法。

注意onreadystatechange屬性要放在send()方法之前。

   var myHttp=createXmlHttpRequest();function myHttp_readyStateChange(){if(myHttp.readyState==4){if(myHttp.status==200){alert(myHttp.responseText); }else{alert("error"+myHttp.status)}}}myHttp.open("GET","http://localhost/myfile.txt",true);myHttp.onreadystatechange=myHttp_readyStateChange; myHttp.send(null);


這段代碼先利用函數createXmlHttpRequest()創建XMLHttpRequest對象,并把結果返回給變量myHttp。

然后定義一個myHttp_readyStateChange()函數,函數體,先測試readyState屬性是否為4,確定請求是否完成。

接下來檢查請求狀態碼status屬性,確定服務器是否返回所請求的數據。

如果該兩個條件都滿足,就顯示responseText?屬性的值(這是XMLHttpRequest異步請求的數據)。


注意:因為即使請求成功,也有可能得不到需要的信息。在請求服務器端可能發生了錯誤(404,500或其他錯誤)。因此,仍然需要檢查請求的狀態碼。一般在檢查了readyState屬性后還要檢查下status狀態碼。


讀取響應數據

XMLHttpRequest對象屬性--------responseText

確保請求已經處理完成(就緒狀態4),服務器給出了正常的響應(狀態碼200),那么我們就可以處理服務器返回的數據了。返回的數據保存在XMLHttpRequest對象的responseText屬性中。返回的文本以什么形式,逗號分隔的值,管道符(|)分隔的值,還是返回長文本字符,都由服務器決定。

返回XMLHttpRequest異步請求的數據,responseText返回的是純文本。

var response = request.responseText.split("|");document.getElementById("order").value = response[0];document.getElementById("address").innerHTML =response[1].replace(/\n/g, "");


將得到的responseText使用javascript中的split()方法從管道符號進行分隔,得到的數組放到變量response中,那么就可以訪問里面的內容了,數組中的第一個值通過response[0]獲得。


與就緒狀態類似,responseText屬性的值在整個請求的生命周期中也會發生變化。不同瀏覽器之間這種變化還不盡相同。

ie7+:狀態為2時開始有值。

其他瀏覽器:狀態為3時開始有值。

測試responseText屬性的值的代碼:

    function myHttp_readyStateChange(){alert(myHttp.responseText);//查看responseText變化if(myHttp.readyState==4){if(myHttp.status==200){// alert(myHttp.responseText); //responseText 返回的僅僅是你PHP代碼執行完,在瀏覽器輸出什么,他就返回什么的.如果它直接返回是PHP代碼,那么說明你的PHP文件沒有執行,查看服務器是否正常運行了PHP文件if(myHttp.responseText=="available"){alert("你的用戶名"+unameValue+"可以用")}else{alert("你的用戶名"+unameValue+"不可以用")}}else{alert("error"+myHttp.status)}}}
}

在所有的文檔和規范中都強調,只有在就緒狀態為4的時候數據才可以安全使用,上面的測試中我們可以知道就算在狀態為3時也是可以得到完整的數據。但是最好還是在4的時候才獲取數據。比較好的做法是是向用戶提供一些反饋,說明處于就緒3時,很快就有響應了------可以在就緒狀態發生變化時更新一些數據,比如,進度條,狀態1時25%,狀態2時50%,狀態3時75%,狀態4時100%(完成)。但是,在不同的瀏覽器中狀態值是不同的。


XMLHttpRequest對象屬性----------responseXML

如果服務器使用XML響應則需要用該屬性來處理響應。

實踐

Ajax驗證表單字段實現在表單提交之前,把數據發送給服務器----允許服務器驗證數據并告訴用戶驗證結果,而無須重載頁面。

因為Ajax是瀏覽器和服務器之間的通信,所以需要一個簡單的服務器應用程序,本例將通過從PHP中請求數據,并給javascript發回響應。


例子:

準備工作

  • web服務器 :我這里用的是一個web小軟件你們可以自己下載本地PHP服務器搭建工具MiniServer(迷你WAMP)下載即用;
  • PHP文件


把相關文件放到服務器中并啟動服務器,然后瀏覽器http打開HTML文件輸入測試

這里通過PHP驗證用戶名和郵箱。


PHP文件formvalidator.php


<?phpheader("Content-Type: text/plain");
header("Cache-Control: no-cache");$array = Array(Array("jmcpeak", "someone@zyx.com"),Array("pwilton", "someone@xyz.com")
);if (isset( $_GET["username"]) || isset( $_GET["email"])) 
{$result = false;if (isset( $_GET["username"])) {$searchTerm = $_GET["username"];for ($i = 0; $i < count($array); $i++) {if (strtolower($array[$i][0]) == strtolower($searchTerm)) {$result = true;}}}if (isset( $_GET["email"])) {$searchTerm = $_GET["email"];for ($i = 0; $i < count($array); $i++) {if (strtolower($array[$i][1]) == strtolower($searchTerm)) {$result = true;}}}$strResult = ($result)?"not available":"available";echo $strResult;
} 
else 
{echo "php是正常工作。恭喜你!";
}
?>


分析該php文件只要不是數組$array里面的用戶名那么就輸出available否則輸出not available。第一個if語句通過get方式得到username的參數值,然后和數組里的用戶名比較。相等的話$result設置為true那么返回給html的結果就是not available(不可用)。


以上PHP文件提供測試username和email。檢查用戶名Http://本機IP(服務器)/formvalidator.php?username=要查詢的用戶名;檢查郵箱Http://本機IP(服務器)/formvalidator.php?email=要查詢的郵箱;

下面給出HTML文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<script>
function checkUname(){var unameValue=document.getElementById("uname").value;if(unameValue==""){alert("請輸入用戶名");return;}var myHttp=createXmlHttpRequest();myHttp.open("GET","formvalidator.php?username="+unameValue,true);myHttp.onreadystatechange=myHttp_readyStateChange; /*每次readyState屬性值發生變化的時候就調用myHttp_readyStateChange()方法*/myHttp.send(null);function myHttp_readyStateChange(){if(myHttp.readyState==4){if(myHttp.status==200){// alert(myHttp.responseText); //responseText 返回的僅僅是你PHP代碼執行完,在瀏覽器輸出什么,他就返回什么的.如果它直接返回是PHP代碼,那么說明你的PHP文件沒有執行,查看服務器是否正常運行了PHP文件if(myHttp.responseText=="available"){alert("你的用戶名"+unameValue+"可以用")}else{alert("你的用戶名"+unameValue+"不可以用")}}else{alert("error"+myHttp.status)}}}
}
function createXmlHttpRequest(){if (window.XMLHttpRequest) {var oHttp = new XMLHttpRequest();return oHttp;} else if (window.ActiveXObject) {var versions = ["MSXML2.XmlHttp.6.0","MSXML2.XmlHttp.3.0"];for (var i = 0; i < versions.length; i++) {try {oHttp = new ActiveXObject(versions[i]);return oHttp;} catch (error) {//do nothing here}}}return null;
}
</script>
<body><form><table><tr><td>用戶名:</td><td><input type="text" id="uname"></td><td><a href="javascript:checkUname()">驗證</a></td></tr><tr><td>郵箱:</td><td><input type="text" id="email"></td><td><a href="javascript:checkEmail()">驗證</a></td></tr></table></form>
</body>
</html>

表單中的用戶名后面的驗證被點擊就執行checkUname()函數,首先獲得ID為uname的值,判斷是否為空,空則提醒輸入并退出函數不執行后面的代碼。條件不符合(不為空)則執行后面的代碼。通過函數createXmlHttpRequest()創建XMLHttpRequest對象并賦值給變量myHttp,?調用open()函數初始化XMLHttpRequest對象 GET方式傳遞參數 ,接收地址是formvalidator.php, true采取異步模式。最后通過send()函數發出請求,前面說過該函數一定要包含參數,實在沒有就給個null。???

前面說過采取異步請求的話XMLHttpRequest對象會提供readyState屬性,該值包含一個數值,代表了不同的請求狀態,每當readyState屬性發生變化的時候都會觸發onreadystatechange事件處理程序。這里把myHttp_readyStateChange里的代碼賦值給onreadystatechange事件處理程序,那么每次readyState屬性發生變化時都執行等號右邊的代碼。

createXmlHttpRequest()函數:根據不同的瀏覽器創建XMLHttpRequest對象;

myHttp_readyStateChange()函數:根據服務器傳回來的信息決定該如何顯示給用戶。

注意:responseText 返回的僅僅是你PHP代碼執行完所輸出的代碼,它在瀏覽器輸出什么,就返回什么的.如果它直接返回是PHP代碼,那么說明你的PHP文件沒有執行,查看服務器是否正常運行了PHP文件


測試:

隨意輸入jmcpeak,pwilton意外的字符點擊驗證:


清空文本框后輸入pwilton點擊驗證:


上面利用Ajax的用法的步驟可以總結為:

創建XMLHttpRequest對象----------open()初始化對象---------send()發出請求----------處理請求返回信息responseText,但是具體的步驟還是按照下面給出的步驟為好。


以后都用這樣的方式用Ajax顯得有的麻煩了,現在我們把運用Ajax的關鍵代碼封裝起來,方便我們以后用吧。

封裝Ajax:創建簡單的Ajax模塊

使用ajax的步驟:

在所有ajax應用程序中基本都雷同的流程:

  1. 從web表單中獲取需要的數據。
  2. 建立要鏈接的url。
  3. 打開到服務器的鏈接。
  4. 設置服務器在完成后要運行的函數。
  5. 發送請求


在程序設計中,代碼重用的概念非常重要。

編寫自定義的Ajax模塊XMLHttpRequest使異步請求更易于使用和管理。


function HttpRequest(sUrl, fpCallback) 
{this.request = this.createXmlHttpRequest();this.request.open("GET", sUrl, true);var tempRequest = this.request;function request_readystatechange() {if (tempRequest.readyState == 4) {if (tempRequest.status == 200) {fpCallback(tempRequest.responseText);} else {alert("An error occurred while attempting to contact the server.");}}}this.request.onreadystatechange = request_readystatechange;
}HttpRequest.prototype.createXmlHttpRequest = function () 
{if (window.XMLHttpRequest) {var oHttp = new XMLHttpRequest();return oHttp;} else if (window.ActiveXObject) {var versions = ["MSXML2.XmlHttp.6.0","MSXML2.XmlHttp.3.0"];for (var i = 0; i < versions.length; i++) {try {oHttp = new ActiveXObject(versions[i]);return oHttp;} catch (error) {//do nothing here}}}return null;
}HttpRequest.prototype.send = function () 
{this.request.send(null);
}

定義HttpRequest(sUrl, fpCallback) 構造函數:

接受兩個參數,sUrl是XMLHttpRequest對象的請求URL。fpCallback是一個回調函數,當收到服務器的響應時(請求的readyState為4,status為200)調用這個回調函數。

構造函數的一行代碼初始化request屬性,執行createXmlHttpRequest()函數并返回給它一個XMLHttpReques對象。

然后用XMLHttpReques對象的open()方法初始化請求對象。該方法將請求類型設置為GET,使用sUrl參數指定要請求的URL,并把請求對象設置為使用異步方式。

接下來定義了request_readystatechange()函數。

在一個函數中定義另一個函數,稱為:“閉包”。“閉包”(這里指request_readystatechange()函數)不能在容器函數(這里指構造函數)以外訪問,但內部函數可以訪問其容器函數的變量和參數。

在這函數前定義了tempRequest變量,這個變量指向當前對象的request屬性的指針。

fpCallback(tempRequest.responseText); 這行代碼調用了構造函數fpCallback()參數定義的回調函數(下面例子中是fun1()),將responseText屬性傳遞給該回調函數。這樣回調函數(fun1())就可以使用從服務器中接收的信息。就是讓傳進來的函數可以使用responseText屬性。


下面的我用上面的代碼寫一個例子

<script>function fun1(srespon){alert(srespon)}var myhttp=new HttpRequest("http://mytext.txt",fun1);myhttp.send();
</script>


fun1()函數將作為HttpRequest()函數的參數傳入,主要是用以如何處理服務器返回的信息。這里是彈出。

然后執行HttpRequest()函數,參數為要請求的服務器地址和處理服務器返回的信息的函數,然后就交給前面定義好的函數處理,結果是返回XMLHttpReques對象給變量myhttp.


上面的模塊封裝了與異步XMLHttpRequest請求相關的代碼,不需要創建請求對象,處理readystatechange事件,或者檢查請求狀態,因為封裝好的HttpRequest()函數會完成所有這些工作。


現在我們用前面創建的Ajax模塊來做前面的表單例子

代碼:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<script>
function checkUname(){var uname=document.getElementById("uname").value;if(uname==""){alert("請輸入用戶名");}var myhttp=new HttpRequest("formvalidator.php?username="+uname,fun01);myhttp.send();
}function fun01(r){if(r=="available"){alert("該用戶可用")}else{alert("該用戶不可用")}}function HttpRequest(sUrl, fpCallback) 
{this.request = this.createXmlHttpRequest();this.request.open("GET", sUrl, true);var tempRequest = this.request;function request_readystatechange() {if (tempRequest.readyState == 4) {if (tempRequest.status == 200) {fpCallback(tempRequest.responseText);} else {alert("An error occurred while attempting to contact the server.");}}}this.request.onreadystatechange = request_readystatechange;
}HttpRequest.prototype.createXmlHttpRequest = function () 
{if (window.XMLHttpRequest) {var oHttp = new XMLHttpRequest();return oHttp;} else if (window.ActiveXObject) {var versions = ["MSXML2.XmlHttp.6.0","MSXML2.XmlHttp.3.0"];for (var i = 0; i < versions.length; i++) {try {oHttp = new ActiveXObject(versions[i]);return oHttp;} catch (error) {//do nothing here}}}return null;
}HttpRequest.prototype.send = function () 
{this.request.send(null);
}</script>
<body><form><table><tr><td>用戶名:</td><td><input type="text" id="uname"></td><td><a href="javascript:checkUname()">驗證</a></td></tr><tr><td>郵箱:</td><td><input type="text" id="email"></td><td><a href="javascript:checkEmail()">驗證</a></td></tr></table></form>
</body></html>

一個javascript方法捕捉用戶輸入表單的信息并將其發送給服務器,另一個javascript方法監聽和處理響應。所有的這些實際上都依賴于第一個javascript方法(?checkUname()方法),它啟動了整個過程。當然你可以在用戶修改表單值得時候觸發該函數onChange="checkUname()".


首先把前面創建好的Ajax模塊函數HttpRequest()復制進去。模塊函數中包含了創建XMLHttpRequest對象,open方法.send()方法還需調用。

然后new通過HttpRequest()函數創建出一個XMLHttpRequest對象返回給變量myhttp。該HttpRequest()函數需要來個參數,要請求的地址和一個處理返回信息的函數(一個函數作為另一個函數的參數稱為回調函數),然后通過send()方法發出請求,這時不用傳入參數是因為在模塊HttpRequest()函數中早已封裝。

var myhttp=new HttpRequest("formvalidator.php?username="+uname,fun01);
myhttp.send();

最后定義一下要做為模塊HttpRequest()函數參數的回調函數fun01(),該回調函數在模塊HttpRequest()函數中需要一個參數來代表responseText(服務器返回的信息)。fun01()的函數體是根據返回的值做出了一些處理。


這里的運用模塊HttpRequest()函數的順序可以總結為:

用new和HttpRequest創建XMLHttpRequest對象----------然后send()出去---------然后處理回調函數


在請求和響應中使用XML

XML是編程中最常用的數據格式之一。在用Ajax的時候你也許也注意到了ajax中的x并且也知道它代表的是XML。還有就是其核心對象的名稱-------XMLHttpRequest.所以很多人會認為XML是ajax的核心技術之一,有的甚至認為XMLHttpRequest對象只能使用XML。但我想說的是XML確實有應用在ajax中,而且XMLHttpRequest也支持這種用法。但是使用ajax不是一定要使用XML。XMLHttpRequest也只是一個名稱。還有就是XML是一種數據格式而不是傳輸協議。

使用XML

在異步應用程序中XML有兩種基本用法:

  1. 以XML格式從網頁向服務器發送請求;
  2. 以XML格式在網頁中從服務器中接收請求。
第一種用法,即用XML發送請求,需要將請求的格式設置為XML,主要的任務是通過構建既符合XML規則又能被服務器理解的方式構造請求。
第二種用法,需要從服務器上接收響應,然后從XML中提取數據。

注意:XML不是一種簡潔,快速和節省空間的格式,和文本相比,XML通常會占用更多額空間,速度也更慢,因為需要再消息中增加XML所需要的標簽和語義。

從客戶機到服務器的XML


假設有:name=rose

使用普通的文本向服務器發送名/值對

在90%的web應用程序中都會用名/值發送到服務器。

var unameValue=document.getElementById("name").value;
var myHttp=createXmlHttpRequest();
url="a.php?username="+escape(unameValue);
myHttp.open("GET",url,true);
myHttp.onreadystatechange=myHttp_readyStateChange; 
myHttp.send(null);

向服務器發送XML

將名/值對轉化為XML

如果你想使用XML作為數據格式,首先要做的是找到一種基本XML格式來存儲數據。顯然,名/值對可以全部轉化成XML元素,以其中的名稱作為元素名,值作為元素內容。

<people><name>rose</name>
</people>

在網絡上傳輸XML之前,要保證服務器以及發送數據的腳本能接受XML,很多人認為只要通過網絡發送XML就能被服務器正確的接收和解析。

實際上,需要注意兩點來保證發送的XML數據能被正確的接收:

  1. 保證向其發送XML的腳本能接受XML數據格式。
  2. 保證腳本發送的XML數據所采用的格式和結構符合服務的要求的格式和結構。
假設服務器接受以下格式的數據:
<address>
<firstname>rose</firstname>    
</address>

看起來和上面的XML類似,但有兩點不同:
  1. 來自客戶機的XML要求封裝在address元素中而不是封裝在people元素中。
  2. 來自客戶機的XML的名字要求使用firstname元素而不是使用name元素。
必須明確服務器期望的格式,并把要發送的數據塞進那種格式。否則,服務器就會就收失敗或者在頁面上顯示錯誤信息。

使用XML發送名/值對

當向服務器發送XML時,更多的代碼是用于獲取數據和包裝成XML,而不是真正的傳輸數據。實際上,只要準備好發送到服務器的XML字符串,發送工作就和普通文本一樣了。
function sendXML(){
var firstname=document.getElementById("firstname").value;
var xmlString="<address>"+"<firstname>"+firstname+"</firstname>"+"</address>"
var myHttp=createXmlHttpRequest();
url="test.php"
myHttp.setRequestHeader("Content-Type","text/xml");
myHttp.onreadystatechange=myHttp_readyStateChange;
myHttp.send(xmlString);
}

請求中的數據必須手工格式化為XML。建立XML之后,按照和發送文本基本相同的方式打開連接。對于XML最好使用POST請求,因為有的瀏覽器限制了GET請求字符串的長度而XML可能很長。此外XML通過send()方法發送,而不是附加在請求url中。
必須編寫如下一段代碼
myHttp.setRequestHeader("Content-Type","text/xml");

告訴服務器要發送的是XML而不是一般的名/值對。如果要使用名/值對,對應行該是:

myHttp.setRequestHeader("Content-Type","text/plain");

注意:使用XML要花和實際數據同樣多的實際來處理尖括號和標簽名稱,這有可能使本來很少的輸入變得非常大。除了這些問題之外,和普通的文本以及名/值對相比,在請求中使用XML實際上沒有多少好處。建議除非和只接受XML的腳本打交道,否則在請求中最好使用普通文本方式而不是XML。

需要向服務器發送XML的理由:
  1. 服務器僅接受XML請求。
  2. 您正在調用一個僅接受XML請求的遠程API。這實際是上一種情況的特列。

從服務器到客戶機的XML

在你發送名稱/值對時,web瀏覽器會發送請求,平臺會響應該請求,并承載一個服務器程序,配合它將那些名/值對轉換成服務器程序可以輕松處理的數據。實際上,每一種服務器技術(JAVA,PHP....)都允許您調傭多種方法來根據名稱獲取值。
如果服務器使用字符串? name=rose&age=15(用&分隔多個參數)應答一個應用程序,客戶機沒有提供任何標準的方法來將每個對拆分成名稱和值,所以你必須手動解析所返回的數據。如果服務器返回一個由名/值對構成的響應,這樣的響應解析難度和使用分號,豎線或其他任何分隔符相同。
對你來說,這就意味著沒有任何簡單的方法在響應中使用純文本,使客戶機以一種標準的方法獲取并解析響應,你需要利用一切手段(分號,等號,豎線等)來拆分這些響應字符,這些都要你自己手動操作,比較麻煩。

注意:在絕大多數HTTP請求中,轉義序列%20用于表示一個空格,文本“name rose"將以”name%20rose“的形式通過http發送。

進入XML

基于以上原因,使用XML的原因就顯而易見了。
向服務器發送數據時,名稱/值對是非常好的選擇,因為服務器和服務器端語言可以輕松解析名/值對。
向客戶機返回數據時使用XML也是如此,有幾種方法可以用服務器中獲得XML響應,并使用較為標準的代碼提取數據。

從服務器接收XML

有兩種基本的方式處理一個來自服務器的XML響應:

  1. 被格式化為XML的純文本
  2. XML文檔,由一個document對象表示

如:

<address><show><firstname>rose</firstname><place>hk</place>  </show>  <show><firstname>rose02</firstname><place>hk02</place>  </show>  <show><firstname>rose03</firstname><place>hk03</place>  </show>  
</address>

將XML作為純文本(無格式的純文本處理)

處理XML最簡單的選擇就是用于處理服務器返回的其他文本片段相同的方法來處理它,也就是說,基本上就是忽略數據格式,只關注服務器的響應。

這種情況下,你要使用請求對象的是responseText屬性,就像服務器返回的不是XML響應時一樣。

        if(myHttp.readyState==4){if(myHttp.status==200){var text=myHttp.responseText;}else{alert("error"+myHttp.status)}}


最終,你將得到把所有一切串聯在一起的XML響應,位于變量text中,如果你輸出此變量,代碼是連續的一個代碼行。

<address><show><firstname>rose</firstname><place>hk</place></show><show><firstname>rose02</firstname><place>hk02</place></show><show><firstname>rose03</firstname><place>hk03</place></show></address>


大多情況下,服務器不會使用空格和回車來格式化XML,而是將一切串聯在一起,當然你的應用程序不會過于在意空格,所以這算不了什么問題,只是會使代碼閱讀起來有些困難。

在這里可以用javascript split()函數來拆分此數據,并通過基本的字符串操作來獲得元素的名稱和值,毫無疑問這是個令人頭疼的過程,你不應該選擇這種方法來獲得XML數據。

將XML當成XML(使用dom處理)

盡管可以如上所述將服務器的XML格式的響應視同為其他任何文本響應來處理,但這樣做沒有很好的理由。你可以使用dom操作XML,javascript中的XMLHttpRequest對象提供了一個屬性(responseXML屬性),可以更好地獲取服務器的XML響應,并且是以DOM document對象的形式獲取它。

現在我們用的不是responseText屬性,而是responseXML屬性,該屬性在XMLHttpRequest對象上可用,它以DOM文檔的格式返回服務器的響應。

if(myHttp.readyState==4){
if(myHttp.status==200){
var xmldoc=myHttp.responseXML;
}else{alert("error"+myHttp.status)}}

現在你就有了一個DOM ?document。

比如我要獲得所有的show元素:

var showelement=xmldoc.getElementsByTagName('show')

現在你可以使用你所了解的全部DOM方法,輕松操縱從服務器處接收到的XML。

解析XML的其他可選方法

除了將XML作為無格式的文本處理或使用DOM處理之外,還有一種選擇,那就是JSON,只要提到XML和ajax應用程序,你就可能會聽到JSON。

大體上,可以用JSON做的事,用DOM都可以做,反之亦然。






處理延遲

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><script>var myhttp=new  HttpRequest("http://localhost/file.txt",fun01);document.getElementById("divloading").style.display="block";myhttp.send();function fun01(r){document.getElementById("divloading").style.display="none";}</script>
</body>
</html>

這段代碼利用前面的HttpRequest()函數創建請求。在發送前,在文檔中獲取id為divloading的html元素,這個元素將告訴用戶,數據正在加載,請求完成時就把它隱藏。



注意事項:

XMLHttpRequest對象不能訪問任何不同來源的文檔或文件。

ajax代碼(具體來說就是XMLHttpRequest對象)只能對所在的同一個域發送請求。也就是說在本地機器上運行的代碼只能對本地機器上的服務器端腳本發送請求。、


如:

http://www.mysite.com/page1.html

http://www.mysite.com/page2.html

這是兩個同源頁面,它們有相同的主機(www.mysite.com),相同的協議(http)相同的端口(80)。因為這兩個頁面是同源頁面,所以其中一個頁面的javascript可以訪問另一個頁面。

再如:

http://www.mysite.com/page1.html

https://www.mysite.com/page2.html

主機相同,協議不同一個http,另一個是https.端口不同一個是80另一個是443.所以任何一個頁面都不能訪問另一個頁面。


XMLHttpRequest對象不能訪問任何不同來源的文檔或文件。這個問題很容易解決:使用一個同源的頁面作為代理(proxy),獲取另一個非同源服務器上的數據。

同源策略還影響到frame/iframe技術,即兩個不同來源的頁面位于同一個框架集中,javascript也就無法與這兩個頁面交互。




最后:

總結下發出請求的步驟

接下來就是在所有 Ajax 應用程序中基本都雷同的流程:

  1. 從 Web 表單中獲取需要的數據。
  2. 建立要連接的 URL。
  3. 打開到服務器的連接。
  4. 設置服務器在完成后要運行的函數。
  5. 發送請求。
下面的示例 Ajax 方法就是按照這個順序組織的:

function callServer() {var city = document.getElementById("city").value;var state = document.getElementById("state").value;if ((city == null) || (city == "")) return;if ((state == null) || (state == "")) return;var url = "/scripts/getZipCode.php?city=" + escape(city) + "&state=" + escape(state);xmlHttp.open("GET", url, true);xmlHttp.onreadystatechange = updatePage;xmlHttp.send(null);
}

記住,XMLHttpRequest?惟一的目的是讓您發送請求和接收響應。其他一切都是 JavaScript、CSS 或頁面中其他代碼的工作:改變用戶界面、切換圖像、解釋服務器返回的數據。


重定向和重新路由

我們來討論下在ajax中不需要考慮的問題----重定向。在http狀態碼中,這是300系列的狀態碼。包括:

  • 301:永久移動。
  • 302:找到(請求被重新定向到另一個url/uri上)。
  • 305:使用代理(請求必須使用一個代理來訪問所請求的資源)
為什么說我們不需要關心重定向問題?因為:
  1. ajax應用程序通常都是為一個特定的服務器端腳本,servlet或應用程序而編寫的,因此有時你會知道資源已經移動了,接下來只需修改請求中的url即可。
  2. ajax只能對所在的同一個域發送請求,也就是說提供生成ajax請求的web頁面的域必須是對這些請求進行響應的域名。因此 ebay.com 所提供的 Web 頁面就不能對一個在 amazon.com 上運行的腳本發出Ajax請求;在 ibm.com 上的 Ajax 應用程序也無法對在 netbeans.org 上運行的 servlets 發出請求。
所以,您的請求是無法重定向到其他服務器上的,而不會產生安全性錯誤。這些情況下,你根本不會得到狀態代碼。通常在調試控制臺中都會產生一個javascript錯誤。因此,在對狀態碼進行考慮后,你就完全可以忽略重定向代碼的問題了。


邊界情況

只有不到5%的ajax請求需要使用2,3的就緒狀態和403之類的狀態碼-----它們只會在一些非常特殊的情況下發生,其中遇到的都是最奇特的問題。雖然這些情況不普遍,但是這些邊界情況卻占據了不部分用戶所碰到的問題的80%。


其他請求類型

HEAD請求

?myHttp.open("HEAD",url,true);

當你這樣生成HEAD請求時,服務器不會像對GET和POST請求一樣返回一個真正的響應。相反,服務器只會返回資源的頭部,這包括響應中內容最好修改的時間,請求資源是否存在和很多其他有用信息。您可以在服務器處理并返回資源之前使用這些信息來了解有關資源的信息。

通過XMLHttpRequest?對象getAllResponseHeaders()可以獲得所有的響應頭的內容

?myHttp.open("HEAD","a.php?username="+unameValue,true);function myHttp_readyStateChange(){if(myHttp.readyState==4){if(myHttp.status==200){alert(myHttp.getAllResponseHeaders())}else{alert("error"+myHttp.status)}}


下圖為從一個向服務器發出的HEAD請求的簡單的ajax應用程序返回的響應頭。


檢查URL

您已經知道了當url不存在時就會出現404錯誤。但可能不是服務器的問題而可能是缺少了一個特定的腳本或servlet,所以有的時候我們希望在生成完整的GET或POST請求之前來檢查這個url。

    function myHttp_readyStateChange(){if(myHttp.readyState==4){if(myHttp.status==200){alert("url存在");}else if(myHttp.status==404){alert("url不存在");}else{alert("error"+myHttp.status);}}

這段代碼,服務器必須對請求進行響應,并構造一個響應來填充內容長度的響應頭,因此不能節省任何處理時間。

有用的HEAD請求

HEAD非常有用的一個領域是用來查看內容的長度或內容的類型,這樣可以確定是否需要發回大量的數據來處理請求,和確認服務器是否試圖返回二進制數據,而不是html,文本或xml(在javascript中,這三種類型數據都比二進制數據更容易處理)。
獲取響應的長度:(myHttp.getResponseHeader("Content-Length");
獲取內容類型:(myHttp.getResponseHeader("Content-Type");
在很多應用程序中,生成HEAD請求并沒有增加任何功能,甚至會導致速度變慢(先生成一個HEAD請求來獲取有關響應的數據,然后再使用一個GET或POST請求來真正獲取響應)。然而,在出現您不確定有關腳本或服務器端組件的情況時,使用HEAD請求可以獲取一些基本的數據,而不需要對響應數據真正進行處理,也不需要大量的帶寬來發送響應。



如果你對狀態碼進行控制,就可以設置應用程序來處理腳本錯誤,非預期的響應以及邊緣問題。結果是應用程序在所有時間都可以正常工作,而僅僅是只能一切都正常的情況下運行。

轉載于:https://www.cnblogs.com/xiaominwu/p/4348003.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259512.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259512.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259512.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

16、Python與設計模式--模板模式

一、股票查詢客戶端 投資股票是種常見的理財方式&#xff0c;我國股民越來越多&#xff0c;實時查詢股票的需求也越來越大。今天&#xff0c;我們通過一個簡單的股票查詢客戶端來認識一種簡單的設計模式&#xff1a;模板模式。根據股票代碼來查詢股價分為如下幾個步驟&#xff…

避免濫用子選擇器

CSS的選擇符是有權重的&#xff0c;當不同選擇符的樣式設置有沖突時&#xff0c;會采用權重高的選擇符設置的樣式。 如果CSS選擇符權重相同&#xff0c;那么樣式會遵循就近原則&#xff0c;哪個選擇符最后定義&#xff0c;就采用哪個選擇符的樣式。 如果忽略了CSS選擇符權重&am…

C++中的空類,默認產生哪些類成員函數?

class Empty { public:/*Empty();//默認構造函數Empty(const Empty& rhs);//拷貝構造函數~Empty();//析構函數Empty& operator(const Empty& rhs);//賦值函數Empty* operator&();//取地址運算符const Empty* operator&() const;//取址運算符 const */ prot…

php exist echo,PHP函數file_exists介紹

&#xfeff;定義和用法file_exists() 函數檢查文件或目錄是否存在。如果指定的文件或目錄存在則返回 true&#xff0c;否則返回 false。exists中文翻譯為存在的意思。語法file_exists(path)例子Example #1<?phpecho file_exists("test.txt");?>輸出&#x…

閉包應用之延遲函數setTimeout

根據HTML 5標準&#xff0c;setTimeout推遲執行的時間&#xff0c;最少是5毫秒。如果小于這個值&#xff0c;會被自動增加到5ms。 每一個setTimeout在執行時&#xff0c;會返回一個唯一ID&#xff0c;把該ID保存在一個變量中&#xff0c;并傳入clearTimeout&#xff0c;可以清除…

并行編程2——多核體系架構

1.1 多核處理器定義 多內核處理器架構是指&#xff1a;芯片設計工程師在單個處理器中集成兩個或多個 “執行內核&#xff08;即計算引擎&#xff09;”。多內核處理器可直接插入到單一處理器基座中。但是&#xff0c;操作系統會把它的每個執行內核作為獨立的邏輯處理器&#x…

21:蘋果和蟲子2

團隊QQ&#xff1a;466373640個人博客&#xff1a;www.doubleq.winc/noi/信息學奧數博客&#xff1a;http://www.cnblogs.com/zwfymqz 1:蘋果和蟲子2 查看提交統計提問總時間限制:1000ms內存限制:65536kB描述你買了一箱n個蘋果&#xff0c;很不幸的是買完時箱子里混進了一條蟲子…

php運行代碼運行退出為0,php – Selenium測試用例返回進程以退出代碼0結束

你使用“phpunit yourTestCase.php”而不是“php yourTestCase.php”嗎&#xff1f;我使用phpunit(3.5.14)和“selenium-server-standalone-2.0rc2.jar”運行你的testfile,沒有問題(除了測試本身失敗)&#xff1a;PHPUnit 3.5.14 by Sebastian Bergmann.ETime: 10 seconds, Mem…

Xcode6中使用initWithTitle:title image:image selectedImage:自定義圖片

使用xcode6來運行項目&#xff0c;發現使用原生的tabbar上的圖片不顯示了。這個問題是因為xcode6中的一些api方法被廢棄了,同時tabbar上圖片的渲染方式發生了改變。先看xcode6中的tabbar api方法的變更&#xff1a;- (void)setFinishedSelectedImage:(UIImage *)selectedImage …

[Node.js]get/post請求

摘要 在很多情況下&#xff0c;我們的web服務器都需要接受客戶端瀏覽器傳遞的參數或者數據。最常見的是get和post請求。 獲取get請求的內容 get請求傳遞的參數在url中&#xff0c;參數部分在?后面。因此可以手動解析后面的內容作為get請求的參數。node.js中url模塊中的parse函…

MyEclipse10 Tomcat7 JDK1.7 配置

第一步.MyEclipse10 Tomcat7 JDK1.7下載 MyEclipse10http://downloads.myeclipseide.com/downloads/products/eworkbench/indigo/installers/myeclipse-10.0-offline-installer-windows.exe Tomcat http://tomcat.apache.org/ Java SE Development Kit 7 WINDOWS版 http://www…

類的靜態成量變量必須初始化

因為類的靜態成員變量是所有實例共用的.所以得在類外初始化. 調用的時候可以通過對象調用,也可以通過類直接調用 classA { public: inti; //有默認值}; classB { public: staticintn;staticA Aobj;}; intB::n 1; //靜態成員變量的初始化A B::Aobj; //靜態…

2階節IIR算法C語言源碼

純C語言軟件算法&#xff0c;沒有做過多優化&#xff0c;只是實現了基本IIR算法 /****************************************************************************** * 二階IIR濾波器單元,采用直接II型 * 由多個2階節&#xff0c;可以組成更多高階的濾波器 * 根據參數的不同&a…

HDU 3709 Balanced Number (數位DP)

題意 求出[x, y] 范圍內的平衡數&#xff0c;平衡數定義為&#xff1a;以數中某個位為軸心&#xff0c;兩邊的數的偏移量為矩&#xff0c;數位權重&#xff0c;使得整個數平衡。 思路 外層枚舉平衡點&#xff0c;然后數位DP即可。設計狀態&#xff1a; dp[pos][o][left_right] …

跳過 Windows RT的UI

RT啟動進入常規桌面 微軟Surface RT發布的時間已經不短了&#xff0c;相信很多朋友都已經熟悉了這個全新的平板&#xff0c;并且已經上手。Surface RT開機默認進入的界面為Windows UI&#xff0c;這對于經常使用App的朋友來說并沒有什么&#xff0c;但是對于那些經常使用Office…

matlab調用mstg,實驗五 雙線性變換法設計IIR數字濾波器

實驗五 IIR 數字濾波器設計一、實驗目的(1)熟悉用雙線性變換法設計IIR 數字濾波器的原理與方法&#xff1b;(2)學會調用MATLAB 信號處理工具箱中濾波器設計函數設計各種IIR 數字濾波器&#xff0c;學會根據濾波需求確定濾波器指標參數。(3)掌握IIR 數字濾波器的MATLAB 實現方法…

Android知識點剖析系列:深入了解layout_weight屬性

前言 Android中layout_weight這個屬性對于經常搗鼓UI的我們來說&#xff0c;肯定不會陌生。但是我們在真正使用這個屬性時&#xff0c;經常會出現一些莫名奇妙的布局效果&#xff1b;如果僅僅知其然而不知其所以然&#xff0c;一些意外的布局效果一定讓我們頗為頭疼。在本文中&…

C++ 中explicit的使用

C提供了關鍵字explicit&#xff0c;可以阻止不應該允許的經過轉換構造函數進行的隱式轉換的發生。聲明為explicit的構造函數不能在隱式轉換中使用。 C中&#xff0c; 一個參數的構造函數(或者除了第一個參數外其余參數都有默認值的多參構造函數)&#xff0c; 承擔了兩個角色。1…

BZOJ 1026 windy數 (數位DP)

題意 區間[A,B]上&#xff0c;總共有多少個不含前導零且相鄰兩個數字之差至少為2的正整數&#xff1f; 思路 狀態設計非常簡單&#xff0c;只需要pos、limit和一個前驅數pre就可以了&#xff0c;每次枚舉當前位時判斷是否與上一位相差2即可。一個需要注意的地方是第一位不用比較…

oracle診斷,Oracle?診斷事件列表

Oracle 診斷事件列表(2013-03-26 18:05:26)標簽&#xff1a;oracle診斷事件itORA-10000: controlfile debug event, name control_fileORA-10001: controlfile crash event1ORA-10002: controlfile crash event2ORA-10003: controlfile crash event3ORA-10004: controlfile cra…