DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> JavaScript高級程序設計 XML、Ajax 學習筆記
JavaScript高級程序設計 XML、Ajax 學習筆記
編輯:關於JavaScript     

第十五章 JavaScript與XML

1.浏覽器對XML DOM的支持

1.1 DOM2級核心

①在DOM2級在document.implementation中引入了createDocument()方法(IE6~8不支持)。

可以創建一個空白XML。

var xmldom = document.implemention.createDocument(namespaceUri,root,docype);

②要創建一個新的文檔元素為<root>的XML文檔,可用如下代碼:

var xmldom = document.implementation.createDocument("","root",null);

aert(xmldom.documentElement.tagName);  //"root"

var child = xmldom.createElement("child");

xmldom.documentElement.appendChild(child);

③檢測浏覽器是否支持DOM2級XML:

var hasXmlDom = document.implementation.hasFeature("XML","2.0");

1.2 DOMParse類型

①Firefox、Opera、Chrome、Safari支持(IE8不支持),DOMParse類型可將XML解析為DOM文檔。

②創建一個DOMParse實例,再調用parseFromString()方法。這個方法接受兩個參數:要解析的XML字符串和內容類型(內容類型始終為"text/xml")。返回值是一個Document實例。

var parser = new DOMParse();

var xmldom = parser.parseFromString("<root><child/></root>","text/xml");

alert(xmldom.documentElement.tagName);  //"root"

alert(xmldom.documentElement.firstChild.tagName);  //"child"

var anotherChild = xmldom.createElement("child");

xmldom.documentElement.appendChild(anthorChild);

var children = xmldom.getElementsByTagName("child");

alert(children.length);  //2

③發生解析錯誤時,仍然會從parseFromString()中返回一個Document對象。但這個對象的文檔元素是<parsererror>(Firefox、Opera);對象根元素第一個子元素為<parsererro>(Safari、Chrome)。

<parseerror>元素的內容是對解析錯誤地描述。通過getElementsByTagName()查找<parsererror>確定是否有解析錯誤。

var parse = new DOMParse();

var xmldom = parser.parseFromString("<root>","text/xml");

var errors = xmldom.getElementsByTagName("parsererror");

if(errors.length > 0 ){

alert("Parsing error!");

}

1.3 XMLSerializer類型

①此類可將DOM文檔序列化為XML字符串。(IE6~8不支持)。

②要序列化DOM文檔,首相必須創建XMLSerializer實例,然後將文檔傳入其serializerToString()方法:

var serializer = new XMLSerializer();

var xml = serializer.serializeToString(xmldom);

alert(xml);

1.4 DOM3級加載和保存

①DOM3級“加載和保存”規范的目的在於將加載、解析和序列化XML文檔的任務標准化,模塊規定了兩個解析方法:同步方法和異步方法。

②檢測DOM3級加載和保存

var hasLSSync = document.implementation.hasFeature("LS","3.0");

var hasLSAsync = document.implementation.hasFeature("LS-Async","3.0");

③DOM3級“加載和保存”還為document.implementation對象添加了下列新屬性和新方法:

□MODE_SYNCHRONOUS:為同步解析方式定義的常量;

□MODE_ASYNCHRONOUS:為異步解析方式定義的常量;

□createLSParse(mode,schemaType):創建一個在指定方式(mode)下運行且符合指定模式(schema)類型的解析器。

□createLSSerializer():創建一個新XML序列化器。

□createLSInput():創建一個新的輸入對象,用於解析/序列化操作。

□createLSOutput():創建一個新的輸出對象,用於解析/序列化操作。

1.4.1 解析XML

(1)同步解析器

①需要先創建同步解析器。如果解析器並不想基於哪個模式進行驗證,為createLSParser()的第二個參數傳入null。如果需要基於XML模式進行驗證,則應為第二個參數傳入"http://www.w3.org/2001/XMLSchema",如果要基於XML DTD進行驗證,則應該為第二個參數傳入"http://www.w3.org/TR/REC-xml"。

②解析之前還要創建一個新的LSInput對象。為此,要使用createLSInput()方法;創建LSInput對象後,還需要將XML字符串賦值給該對象的stringData屬性。

③解析完成後,就會返回一個XML DOM文檔對象

④如果在同步解析方式下發生解析錯誤,則會拋出錯誤。

⑤示例:

var implementation = document.implementation;

var parser = implementation.createLSParser(implementation.MODE_SYNCHRONOUS,null);

var input = implement.createLSInput();

input.stirngData = "<root>";

try{

xmldom = parser.parse(input);

}catch(ex){

alert("Parsing error!");

}

(2)異步解析器

①需要在createLSParser()的第一個參數的位置上傳入常量MODE_ASYNCHRONOUS。

②通過addEventListener()來預訂load事件,以便知道文檔何時解析完畢。

③如果異步解析期間發生錯誤,則不會觸發load事件。要捕獲這個錯誤,需要使用LSParser對象上一個名叫domConfig的特殊接口定義一個錯誤處理程序。(BUG:Opera9.5不會觸發load)

④domConfig為DOMConfiguration類型的實例,表示針對特定文檔的解析和格式化規則。LSParser會用此對象指定額外配置信息,需調用setParameter()方法。其中一個參數是"error_handler",用於指定處理解析錯誤的函數。

var implementation = document.implementation;

var parser = implementation.createLSParser(implementation.MODE_ASYNCHROUNS,null);

var input = implementation.createLSInput();

input.stringData = "<root>";

//預訂load事件,但不會觸發load事件

parser.addEventListener("load",function(event){

var xmldom = event.newDocument;

var input = event.input;

alert(xmldom.documentElement.tagName); //"root"

alert(xmldom.documentElement.firstChild.tagName);  //"child"

var anotherChild = xmldom.createElement("child");

xmldom.documentElement.appendChild(anotherChild);

var children = xmldom.getElementsByTagName("child");

alert(children.length);  //2

},false);

parser.domConfig.setParameter("error_handler",fucntion(ex){

alert("Parsing error!");

});

//開始解析

parser.parse(input);

1.4.2 其它解析方式

通過LSParser還可以執行兩種類型的解析:解析來自URI的文件和基於上下文解析。

(1)解析來自URI的XML。

①不用創建LSInput。

②開始解析時調用parseURI()方法,並為其傳入一個指向有效XML的URI。Parser.parseURI("example.xml");

(2)基於上下文解析

①首先解析字符串,然後將解析結果插入另一個文檔。

②使用parseWithContext()方法接受3個參數:LSInput對象、上下文節點和要執行的操作。

□LSInput對象的stringData屬性中必須包含XML片段的代碼,不能含有XML序言內容(prolog)。

□上下文節點是解析完的片段該插入的地方。

□要執行的操作必須是下列LSParser常量之一。

◇ACTION_APPEND_AS_CHILDERN:將解析結果作為子節點添加到上下文節點中。

◇ACTION_REPLACE_CHILDREN:先移除上下文節點的所有節點,然後將解析結果作為上下文節點的子節點插入。

◇ACTION_INSERT_BEFORE:將解析結果作為上下文節點的同輩節點,插入到上下文節點前面。

◇ACTION_INSERT_AFTER:將解析結果作為上下文節點的同輩節點,插入到上下文節點後面。

◇ACTION_REPLACE:用解析結果替換上下文節點。

◇在解析錯誤時,以上操作均會被取消。

var implementation = document.implement;

var parser = implementation.createLSPareser(implementation.MODE.SYNCHRONOUS,null);

var input = implementation.createLSInput();

input.stringData = "<root/>";

var xmldom = parser.parse(input);

var newInput = implementation.createLSInput();

newInput.StringData = "<child/>";

parse.parseWithContext(newInput,xmldom.documentElement,parser.ACTION_APPEND_AS_CHILDREN);

alert(xmldom.documentElement.firstChild.tagName);  //"child"

1.4.3 序列化XML

①要調用document.implementation上的createLSSerialization()方法,創建一個LSSerializer對象。LSSerializer對象的主要方法是writeToString(),接受一個節點類型參數並返回該節點的XML代碼字符串表述。

②通過LSSerializer對象的domCOnfig屬性來設置適合打印輸出的XML字符串格式,即將該屬性的"format_pretty_print"參數設為true。

③序列化期間發生錯誤,錯誤會被拋出。通過將writeToStirng()放try-catch語句中,可以測試是否發生了錯誤。

var serializer = implementation.createLSSerializer();

serializer.domConfig.setParameter("format_pretty_print",true);

var xml = "";

try{

Xml = serializer.writeToString(xmldom);

}catch(ex){

Alert("Serialization error occurred");

}

alert(xml);

1.5 IE對XML的支持

①IE有6種不同的XML文檔版本可供選擇,只建議其中3種:

□MSXML2.DOMDocument:為方便腳本處理而更新的版本,建議僅在特殊情況下作後備版本使用。

□MSXML2.DOMDocument.3.0:為了在JavaScript中使用,這是最低的建議版本。

□MSXML2.DOMDocument.6.0:通過腳本能夠可靠地處理的最新版本。

□確定可用版本:

function createDocument(){

if(typeof arguments.callee.activeXString ! = "string"){

var versions = ["MSXML2.DOMDocument.6.0","MSXML2.DOMDocument.3.0","MSXML2.DOMDocument"];

for(var i = 0, len = versions.length; i < len; i++){

try{

var xmldom = new ActiveXObject(versions[i]);

arguments.callee.activeXString = versions[i];

return xmldom;

}catch(ex){

//跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}

②要解析XML字符串,先創建XML DOM文檔,然後調用其loadXML()方法。

var xmldom = createDocument();

xmldom.loadXML("<root><child/></root>");

□在新DOM文檔中填充了XML內容後,就可以像操作其他DOM文檔一樣操作它了(可以使用任何方法和屬性)

③如果解析過程中出錯,可以在parseError屬性對象中找到錯誤。包含多個保存錯誤信息的屬性。

□errorCode:錯誤類型的數值編碼;沒有發生錯誤時值為0

□filePos:文件中導致錯誤發生的位置。

□line:發生錯誤的行。

□linepos:發生錯誤的行中的字符。

□reason:對象錯誤地文本解析。

□srcText:導致錯誤的代碼。

□url:導致錯誤的文件的URL。

□parseError的valueof()方法返回errorCode的值。

if(xmldom.parseError != 0){

alert("An error occurred: \n Error Code:"+xmldom.parseError.errorCoed + "\n" 

+ "line:" + xmldom.parseError.line + "\n"

+ "line.Pos" + xmldom.parseError.linepos + "\n"

+ "Reson:" + xmldom.parseError.reason

);

}

1.5.1序列化XML

IE序列化XML的能力內置在了XML DOM文檔中。每個XML DOM節點都有一個xml屬性,其中保存著表示該節點的XML字符串。alert(xmldom.xml)

1.5.2 加載XML文件

①與DOM3級功能類似,要加載的XML文檔必須與JS代碼來自同一服務器。

②加載文檔的方式也可以分為同步和異步兩種。要指定加載文檔的方式,可以設置async屬性,true表示異步(默認),false表示同步。使用load(URI)方式加載。

③異步加載XML,需為XML DOM文檔的onreadystatechange事件指定處理程序。有4個就緒狀態(ready state)

□1:DOM正在加載數據。

□2:DOM已經加載完數據。

□3:DOM已經可以使用,但某些部分可能還無法訪問。

□4:DOM已經完全可以使用。

□實際上,只需要關注狀態4。通過XML文檔的readyState屬性可得其就緒狀態。

var xmldom = createDocument();

xmldom.async = true;

xmldom.onreadystatechange = function(){

if(xmldom.readyState == 4){

if(xmldom.parseError != 0){

Alert("An error occurred");

}else{

//其他xmldom操作

}

}

}

xmldom.load("exmaple.xml");

注:

□onreadystatechange事件指定處理語句須在調用load()方法之前。

□在事件處理內部由於ActiveX控件為預防錯誤,不允許使用this。

1.6 跨浏覽器處理XML

function parseXML(xml){

var xmldom = null;

if(typeof DOMParser != "undefined"){

xmldom = (new DOMParser()).parseFromString(xml,"text/xml");

var errors = xmldom.getElementsByTagName("parsererror");

if(errors.length){

throw new Error("XML parsing error:" + errors[0].textContent);

}

}else if(document.implementation.hasFeature("LS","3.0")){

var implementation = document.implementation;

var parser = implementation.createLSParser(implementation.MODE_SYNCHRONOUNS,null);

var input = implementation.createLSInput();

input.stringData = xml;

xmldom = parser.parse(input);

}else if(typeof ActiveXObject != "undefined"){

xmldom = createDocument();

xmldom.loadXML(xml);

if(xmldom.parseError != 0){

throw new Error("XML parsing error:" + xmldom.parseError.reason);

}

}else{

throw new Error("No XML parser available.");

}

return xmldom;

}

用此函數解析XML字符串時,應該放在try-catch語句中

var xmldom = null;

try{

xmldom = parseXml("<root><child/><root>");

}

catch(ex){

alert(ex.message);

}

■序列化XML兼容代碼

function serializeXml(xmldom){

if(typeof XMLSerializer != "undefined"){

return(new XMLSerializer()).serializeToString(xmldom);

}else if(document.implementation.hasFeature("LS","3.0")){

var implementation = document.implementation;

var serializer = implemetation.createLSSerializer();

return serializer.writeToString(xmldom);

}else if(typeof xmldom.xml != "undefined"){

return xmldom.xml;

}else{

throw new Error("Could not serialize XMLDOM.");

}

}

2.浏覽器對XPath的支持

2.1 DOM3級Xpath

①DOM3級支持XPath,檢測浏覽器支持:

Var supportsXPath = document.implementation.hasFeature("XPath","3.0");

②DOM3級XPath中最重要的兩個類型:XPathEvaluator和XPathResult。

③XPathEvalutor用於特定的上下文中隊XPath表達式求值。有3個方法:

□createExpression(expression,nsresolver):將XPath表達式及相應的命名空間信息轉換成一個XPathExpression,這是查詢的編譯版。在多次使用一個查詢時很有用。

□createNSResolver(node):根據node的命名空間信息創建一個新的XPathNSResolver對象。在基於使用命名空間的XML文檔求值時,需要使用XPathNSResolver對象。

□evaluate(expression,context,nsresolver,type,result):在給定的上下文中,基於特定的命名空間信息來對XPath表達式求值。剩下的參數表示如何返回結果。

□在支持DOM3級的浏覽器中,Document類型通常都是與XPathEvaluator接口一起實現的。

④上面3個方法中,evalute最常用。接受5個參數:

□XPath表達式

□上下文節點

□命名空間解析器(只在XML代碼中使用了XML命名空間時有必要指定,否則為null)

□返回結果的類型(見書P415)

□保存結果的XPathResult對象(通常是null,因為結果也會以函數值形式返回)

■返回結果類型為以下的其中一個:

◇XPathResult.ANY_TYPE

◇XPathResult.NUMBER_TYPE

◇XPathResult.STRING_TYPE

◇XPathResult.BOULEAN_TYPE

◇XPathResult.UNORDER_NODE_ITERATOR_TYPE

◇XPathResult.ORDERED_NODE_SNAPSHOT_TYPE

◇XPathResult.ANY_UNORDERED_NODE_TYPE

◇XPathResult.FIRST_ORDERED_NODE_TYPE

1)指定的是迭代器結果,須用iterateNext()方法從節點中取得匹配節點,無則返回null。

var result = xmldom.evalute("employee/name",xmldom.document,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);

if(result !== null){

var node = result.iterateNext();

while(node){

alert(node.tagName);

node = node.iterateNext();

}

}

2)指定的是快照類型,就必須使用snapshotItem()和snapshotLength屬性。

1.單節點結果

指定常量XPathResult.FIRST_ORDER_NODE.TYPE會返回第一個匹配節點,可通過singleNodeValue屬性來訪問該節點。

2.簡單類型結果

booleanValue、numberValue和stringValue

3.默認類型結果

4.命名空間支持

□對於利用了命名空間的XML文檔,XPathEvaluator必須知道命名信息,然後才能正確地進行求值。

□第一種方法是通過createNSResolver()來創建XPathNSResolver對象,這個方法接受一個參數,即文檔中包含命名空間定義的節點。

Var nsresolver = xmldom.createNSResolver(xmldom.documentElement);

Var result = xmldom.evaluate("wrox:book/wrox:author",xmldom.document,nsresolver,XPathResult.ORDERED_NODESNAPSHOTTYPE,null);

Alert(result.snapshotlength);

□第二種方法是定義一個函數,讓它接受一個命名空間前綴,返回關聯的URI。

Var nsresolver = function(prefix){

Switch(prefix){

Case "wrox" : return "http://www.wrox.com/";

//其他前綴

}

};

Var result = xmldom.evaluate("count(wrox:book/wrox:author)",xmldom.document,nsresolver,XPathResult.NUMBER_TYPE,null);

2.2 IE中的XPath

①IE對XPath的支持是內置在XML DOM文檔對象中的。含有兩個方法。

□selectSingleNode()方法接受一個XPath模式,在找到匹配節點時返回第一個匹配的節點。

var element = xmldom.documentElement.selectSingleNode("employee/name");

□selectNodes(),接受一個XPath模式作參數,返回與模式匹配的所有節點的NodeList(如果沒有匹配的節點,則返回一個包含零項的NoedList)。

Var elements = xmldom.documentElement.selectNodes("employee/name");

Alert(elements.length);

②IE對命名空間的支持

□必須知道自己使用的命名空間,並按格式創建一個字符串:

"xmlns:prefix1 = 'uri1' xmlns:prefixf2 = 'uri2' xmlns:prefix3:'uri3' "

□將上述格式字符串傳入到XML DOM文檔對象的特殊方法setProperty()中。

□setProperty()接受兩個參數:要設置的屬性名和屬性值。這裡屬性名應為"SelectionNameSpaces",屬性值是前面格式的字符串。

xmldom.setProperty("selectionNameSpaces","xmlns:wrox = http://www.wrox.com");

var result = xmldom.documentElement.selectNodes("wrox:book/wrox:author");

2.3 跨浏覽器使用XPath

□selectSingleNode()函數兼容代碼

function selectSingleNode(context,expression,namespace){

var doc = (context.nodeType != 9 ? context.ownerDocument : context);

if(typeof doc.evaluate != "undefined"){

var nsresolver = null;

if(namespace instanceof Object){

nsresolver = fucntion(prefix){

return namespaces[prefix];

};

}

var result = doc.evaluate(expression,context,nsresolver,XPathResult.FIRST_ORDERED_NODE_TYPE,null);

return(result !== null ? Result.singleNodeValue : null);

}else if(typeof context.selectSingleNode != "undefined"){

//創建命名空間字符串

if(namespaces instanceof Object){

var ns = "";

for(var prefix in namespaces){

if(namespaces.hasOwnproperty(prefix)){

ns += "xmlns:" + prefix + "='" + namespaces[prefix] + "' ";

}

}

doc.setProperty("SelectionNamespaces",ns);

}

return context.selectSingleNode(expression);

}else{

throw new Error("No Xpath engine found.");

}

}

□selectNodes()函數兼容代碼

P420略

3.函數對XSLT的支持

XSLT是與XML相關的一種技術,它利用XPath將文檔從一種表現形式轉換成另一種表現形式。

3.1 IE中的XSLT轉換

1.簡單的XSLT轉換

□最簡單方法:XSLT、XML分別加載到一個DOM文檔中,再使用transformNode()方法。

□transformNode()方法:只有一個參數——包含XSLT樣式表的文檔。返回一個包含轉換信息的字符串。

□可在xmldom各個節點機型轉換。

//加載xmldom各個節點進行轉換

xmldom.load("employees.xml");

xsltdom.load("employees.xslt");

//轉換

var result = xmldom.transformNode(xsltdom);

2.復雜的XSLT轉換

①基本原理:

a.將xml加載到“線程安全的XML DOM”中。

b.將XSLT加載到“XSL模板”中

c.使用“XSL處理器”進行轉換。

□自由線程DOM:MSXML2.FreeThreadedDOMDocument

□XSL模板:MSXML2.XSLTemplate

□XSL處理器:調用XSL模板的createProcessor()創建XSL處理器。

②把XSLT樣式表加載到一個線程安全的XML文檔中。

function createThreadSafeDocument(){

if(typeof arguments.callee.activeXString != "string"){

var versions = ["MSXML2.FreeThreadedDOMDocument.6.0","MSXML2.FreeThreadedDOMDocument.3.0","MSXML2.FreeThreadedDOMDocument\"];

for(var i=0,len = version.length; i<len; i++){

try{

var xmldom = new ActiveXObject(versions[i]);

arguments.callee.activeXString = versions[i];

return xmldom;

}catch(ex){

// 跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}

□線程安全的XML DOM與常規XML DOM使用方式一致。

var xsltdom = createThreadSafeDocument();

xsltdom.async = fasle;

xsltdom.load("employee.xslt");

③為自由線程DOM指定XSL模板

fucntion createXSLTemplate(){

if(typeof arugments.callee.activeXString != "string"){

var versions = ["MSXML2.XSLTemplate.6.0","MSXML2.XSLTemplate.3.0","MSXML2.XSLTemplate"];

for(var i=0,len=versions.length;i<len;i++){

try{

var template = new ActiveXObject(versions[i]);

arguments.callee.activeXString = version[i];

return template;

}catch(ex){

//跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}

□使用createXSLTemplate()函數創建用法:

var template = createXSLTemplate();

template.stylesheet = xsltdom;

var processor = template.createProcessor();

processor.input = xmldom;

processor.transform();

var result = processor.output;

④創建XSL處理器之後,須將要轉換的節點指定給input屬性。然後,調用transform()方法執行轉換並將結果左字符串保存在output屬性中。

⑤使用XSL處理器可以對轉換進行更多的控制,同時也支持更高級的XSLT特性。

□addParameter():兩個參數:要設置的參數名稱(與在<xsl:param>的name特性中給指定的一樣)和要指定的值(多數是字符串,也可以是數值或布爾值)。

□setStartMode():接受一個參數,即要為處理器設置的模式。

□reset():重置處理器,清除原先的輸入和輸出屬性、啟動模式及其它指定的參數。processor.reset();

3.2 XSLTProcessor類型(非IE浏覽器支持)

①基本原理:

a.加載兩個DOM文檔,一個基於XML,另一個基於XSLT。

b.創建一個新XSLTProcessor對象

c.使用importStylesheet()方法指定一個XSLT

d.最後使用transformToDocument()或transfromToFragment()方法可得一個文檔片段對象。

var processor = new XSLTProcessor();

processor.importStylesheet(xsltdom);

□transformToDocument():只要傳入XML DOM,就可將結果作為一個完全不同的DOM文檔使用。

□transformToFragement():兩個參數:要轉換的XML DOM和應該擁有結果片段的文檔

var fragment = processor.transformToDocument(xmldom,document);

②使用參數:

□setParameter():3個參數:命名空間URI(一般為null)、參數內部名稱和要設置的值

□getParameter():取得當前參數的值,兩個參數:命名空間和參數內部名。

□removeParameter():移除當前參數的值,兩個參數:命名空間和參數內部名。

③重置處理器

□reset()方法:從處理器中移除所有參數和樣式表。

3.3 跨浏覽器使用XSLT

IE對XSLT轉換支持與XSLTProcessor區別太大,跨浏覽器兼容性最好的XSLT轉換技術,只能是返回結果字符串。

function transform(context,xslt){

if(typeof XSLTProcess != "undefined"){

var processor = new XSLTProcessor();

processor.importStylesheet(xslt);

var result = processor.transfromToDocument(context);

return(new XMLSerialize()).serializeToString(result);

}else if(typeof context.transforamNode != "undefined"){

return context.transformNode(xslt);

}else{

throw new Error("No XSLT processor available.");

}

}

第十六章 E4X (略)

第十七章 Ajax與JSON

1.XHR對象

①IE6需要使用MSXML庫中的一個ActiveX對象實現,而其他浏覽器原生支持XHR對象。

function createXHR(){

if(typeof XMLHttpRequest != "undefined"){

return new XMLHttpRequest();

}else if(typeof ActiveXobject != "undefined"){

if(typeof arguments.callee.activeXString != "string"){

var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];

for(var i=0, len = versions.length; I <len; i++){

try{

var xhr = new ActiveXObject(versions[i]);

Arguments.callee.activeXString = versions[i];

return xhr;

}catch(ex){

//跳過

}

}

}

return new ActiveXObject(arguments.callee.activeXString);

}else{

throw new Error("No XHR object available");

}

}

1.1 XHR的用法

①open()方法

□接受3個參數:要發送的請求的類型(“get”、“post”等)、請求的URL和表示是異步發送請求的布爾值。

□參數URL是相對於執行代碼的當前頁面(當然也可以使用絕對路徑);

□調用open()方法並不會真正發送請求,而只是啟動一個請求以備發送。

②send()方法

□要發送特定的請求,必須使用send()方法啟動。

□接受一個參數,即要作為請求主體發送的數據。如果不需要通過請求主體發送數據,則必須傳入null,因為這個參數對有些浏覽器來說是必須的。

□調用send()之後,請求就會被分派到服務器。

③相應的數據會自動填充XHR對象的屬性,相關的屬性簡介如下:

□responseText:作為相應主體被返回的文本。

□responseXML:如果響應的內容是“text/xml”或“application/xml”,這個屬性中將保存含著響應數據的XML DOM文檔。

□status:響應的HTTP狀態。

□statusText:HTTP狀態的說明。

④處理響應的判斷

□檢查status屬性,以確定響應成功返回。

□HTTP狀態代碼為200是成功的標志,此時responseText、responseXML應能訪問。

□HTTP狀態代碼為304表示請求的資源沒修改,可使用緩存值。

⑤同步請求

xhr.open("get", "example.txt", false);

xhr.send(null);

if( (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){

alert(xhr.statusText);

}else{

alert("Request was unsuccessful:" + xhr.status);

}

⑥異步請求

1)發送異步請求還需要檢測XHR對象的readyState屬性,該屬性表示請求/響應過程的當前活動階段。取值如下:

□0:未初始化。尚未調用open()方法。

□1:啟動。已調用open()方法,未調用send()方法。

□2:發送。已調用send()方法,但尚未接收到響應。

□3:接收。已接收到部分響應數據。

□4:完成。已經接收到全部響應數據,而且已經可以在客戶端使用了。

2)readyState值的變化會觸發readyStatechange事件。由於並非所有浏覽器支持DOM2級方法,因此用DOM0級添加處理程序。

var xhr = createXHR();

xhr.onreadystatechange = function(){

if(xhr.readyState == 4){

if( (xhr.staus >= 200 && xhr.status < 300) || xhr.status == 304){

alert(xhr.responseText);

}else{

alert("Request was unsuccessful: " + xhr.status);

}

}

};

xhr.open("get","example.txt", true);

xhr.send(null);

⑦在接收到響應之前還可以調用abort()方法取消異步請求。xhr.abort();

1.2 HTTP頭部信息

XHR對象提供了操作“請求頭部”和“響應頭部”信息的方法。

①請求頭部

1)請求頭部信息

□Accept:浏覽器能夠處理的內容類型。

□Accept-Charset:浏覽器能夠顯示的字符集。

□Accept-Encoding:浏覽器能夠處理的壓縮編碼。

□connection:浏覽器與服務器之間連接的類型。

□Cookie:當前頁面設置的任何cookie。

□Host:發出請求的頁面所在的域。

□Referer:發出請求的頁面的URI。

□User-Agent:浏覽器的用戶代理字符串。

②setRequestHeader()方法可以設置自定義的請求頭部信息。

□接收兩個參數:頭部字段名稱和頭部字段的值。

□要成功發送請求頭部信息,必須在調用open()方法之後且調用send()方法之前。

③getResponseHeader()方法,傳入頭部字段名稱,可以取得相應的響應頭部信息。

④getAllResponseHeader()方法,取得一個包含所有頭部信息的長字符串。

1.3 GET請求

①常用語服務器查詢信息。

②GET請求經常會發生查詢字符串格式問題。查詢字符串中每個參數的名稱和值都必須使用encodeURIComponent()進行編碼。

③輔助向現有URL末尾添加查詢字符串參數:

function addURLParam(url, name, value){

url += (url.indexOf("?") == -1 ? "?" : "&" );

url += encodeURIComponent(name) + "=" + encodeURIComponent(value);

return url;

}

1.4 POST請求

①通常用於向服務器發送應該被保存的數據。

②xhr.open("post","example.php",true);發送post請求的第二步就是向send方法中傳入某些數據。

1.5浏覽器差異

①IE

□IE為XHR對象添加了一個timeout屬性,表示請求在等待響應。

□規定時間內沒有接收到響應,就出發timeout事件,進而調用ontimeout事件處理程序。

②Firefox

1)load事件

2)progress事件

2.跨域請求

①IE中XDomainRequest對象

1)XDR與XHR區別

□cookie不會隨請求發送,也不會隨響應返回。

□只能設置請求頭部信息中的Content-Type字段。

□不能訪問響應頭部信息。

□只支持GET和POST請求。

□XDR只能訪問Access-Control-Allow-Origin頭部設置為有當前域的資源。

2)所有XDR請求都是異步執行的,不能創建同步請求。

□返回請求之後,會觸發load事件,響應的數據也會保存在response屬性中。

□接收到響應後,只能訪問響應的原始文本,沒有辦法確定響應的狀態代碼。

□響應有效會觸發load事件,如果失敗(包括響應中缺少Access-Control-Origin頭部)就會觸發error事件。

□XDR也支持timeout屬性以及ontimeout事件處理程序。

□為了支持POST請求,XDR對象提供了ontentType屬性,用來表示發送數據的格式。

□在請求返回前調用abort()方法可終止請求。

var xdr = new XDomainRequest();

xdr.onload = function(){

alert(xdr.responseText);

};

xdr.timeout = 1000;

xdr.ontimeout = function(){

alert("Request took too long.");

};

xdr.open("get","http://www.xx.com/page/");

xdr.send(null);

②Firefox

1)要求遠程資源有權決定自身是否可以被遠程浏覽器訪問。

□這需要通過設置Access-Contro-Allow-Origin頭部實現。

□要訪問另一個域資源,可以使用標准XHR對象,並為open()方法傳入一個絕對URL。

2)與IE中XDR對象不同,跨域XHR對象允許訪問status和statusText屬性,也支持同步請求。

3)跨域XHR的額外限制如下:

□不能使用setRequestHeader()設置自定義頭部。

□不會發送也不會接受cookie

□getAllRequestponseHeaders()方法只能返回空字符串。

3.JSON

①JSON是純文本,而不是JavaScript代碼。JSON的設計意圖在服務器端構建格式化的數據,然後再將數據發送給浏覽器。

②由於JSON在JavaScript中相當於對象和數組,因此JSON字符串可以傳遞給eval()函數,讓其解析並返回一個對象或數組的實例。

③如果你是自己編寫代碼來對JSON求值,最好將輸入文本放在一對圓括號中。因為eval()在對輸入的文本求值時,是將其作為JS代碼而非數據格式看待。在對以左花括號開頭的對象求值時,就好像是遇到一個沒有名字的JavaScript語句,會導致錯誤。將文本放在一對圓括號中可以解決這個問題,因圓括號表示值而不是語句。

var object1 = eval("{}");  //拋出錯誤

var object2 = eval("({})");  //沒有問題

var object3 = eval("(" + jsonText + ")");  //通用解決方案

3.1在Ajax中使用JSON

①Douglas Crockford的JSON序列化器/解析器。www.json.org/js.html

②在上述庫中,有一個全局JSON對象,有兩個方法:parse()和stringify()。

③parse()方法:

□兩個參數:JSON文本和一個可選的過濾函數。在傳入的文本是有效地JSON情況下,parse()方法返回傳入數據的一個對象表示。

□例子:var object = JSON.parse("{}"); 與直接使用eval()不同的是,這裡不需要傳入的文本家圓括號(內部自動處理)。

□第二個參數是一個函數,這個函數以一個JSON鍵和值作為參數。要想讓作為參數的鍵出現在結果對象中,該函數必須返回一個值。

var jsonText = "{\"name\":\"Nicholas\",\"age\":29,\"author\":true}";

var object = JSON.parse(jsonText,function(key,value){

switch(key){

case "age" : return value+1;

case "author" : return undefined;

default : return value;

}

});

alert(object.age);  //30

alert(object.author); //undefined

④JSON同樣也是向服務器發數據的流行格式。發送數據時,一般會把JSON放到POST請求主體中,而JSON對象的stringify()方法正是為此而設計。

⑤stringify()方法:

□三個參數:要序列化的對象、可選的替換函數(用於替換未受支持的JSON值)和可選的縮進說明符(可以是每個級別縮進的空格數,也可以是用來縮進的字符)。

var contact = {

name : "Nicholas C. Zakas",

email : "[email protected]"

};

var jsonText = JSON.stringify(contact);

alert(jsonText);

□JSON序列化支持的類型:字符串、數值、布爾值、null、對象、數組和Date(Date將被換成字符串形式)。其他不支持類型將被移除,可通過stringify()第二個參數所傳入的函數改變行為。

3.2安全

①JSON缺點:使用eval(),有可能受到XSS攻擊。

②建議使用Crockford的庫,可妥當解析JSON字符串,過濾其中惡意代碼。降低遭受代碼式XSS攻擊的可能性。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved