out-of-band调用模型
使用AJAX功能在Web页面中发挥作用的关键因素是发送out-of-band HTTP请求。out-of-band是指通过独立于浏览器的组件发出HTTP请求。out-of-band调用由HTML页面事件通过脚本触发,随后会由代理组件处理。在AJAX框架中,这个代理组件基于XMLHttpRequest对象。
XMLHttpRequest是浏览器对象,它可以通过JavaScript脚本进行调用。XMLHttpRequest能够向指定的URL发送HTTP请求,并等待它被处理,该过程即能以同步方式执行,也能以异步方式执行。当响应数据就绪后,这个代理会调用用户定义的JavaScript回调来刷新页面中需要更新的部分。下图描绘了该模型的总体结构:
浏览器提供了一种代表页面当前内容的对象模型--DOM。利用DOM,JavaScript回调函数能够实现页面的局部刷新,由此而无需重新加载整个页面。
若要利用AJAX的特性,浏览器要具备哪些功能呢?
1. 使客户端代码能够发出out-of-band HTTP调用的代理机制。
2. 可更新的DOM。
3. 支持JavaScript。
万维网联合会(W3C)制定了可更新DOM的标准。代理组件W3C标准也被制定,它采用了现有的XMLHttpRequest对象,作为一种浏览器暴露的接口运行脚本代码执行HTTP客户端功能。
HTML文档对象模型的作用
页面的文档对象模型(Document Object Model,DOM)是一种规范,它定义了一套与平台和语言无关的接口,用于访问或更新HTML和XML文档的内容。DOM提供了一套标准的对象,代表着组成HTML和XML文档的元素。将这些对象合在一起,便构成一套用于访问和操纵HTML页面子元素的标准接口。
DOM应用程序编程接口能将页面呈现为一个树形结构。对Web页面来说,每个节点映射到代表HTML标签的对象。这种对象有作用于相应HTML标签的属性和方法。在DOM中,有3个与节点有关的基本操作:
1. 节点的查找。
2. 节点的创建。
3. 节点的操纵。
W3C DOM由3个级别组成,对应于浏览器的3方面功能。
从动态HTML到标准DOM
从IE 4.0开始引入为名为“动态HTML(Dynamic HTML,DHTML)”的对象模型,它使页面开发者能够通过JavaScript动态更新当前页面。DHTML的成功促使了标准文档对象模型(W3C的DOM)出现。不难看出,DOM源于DHTML,但比DHTML更普遍。
当今的大多数浏览器都同时支持DOM和DHTML。我们应使用哪套模型?具体来说,为更新某些内容,是应该获取目标HTML标签对应节点的文本子节点(DOM方式),还是获取相应节点的引用,并使用innerHTML属性(DHTML方式)?类似的,如果要添加新元素,是应该创建新的元素,还是通过innerHTML更新整块HTML呢?
事实上,DOM API比使用innerHTML慢得多。如果希望通过DOM来动态生成用户界面,则需要创建每个元素,并将其追加到相应的容器中,且设置其属性。而DHTML只需定义所需的HTML,通过innerHTML便可呈现。随后,浏览器会将开发者指定的标记显示出来,从而完成剩余的工作。
总的来说,DHTML和DOM这两种操纵方式是否使用,取决于具体的上下文。有很多Web站点进行了性能测试,DHTML总是获胜者。不过,只要正确使用DOM,其速度也能满足要求。
XMLHttpRequest对象
XMLHttpRequest对象是Microsoft设计并构建的,但不久就得到了Mozilla的支持。如今,大多数Web浏览器都完全支持它。对于不同浏览器,彼此间对该对象的内部实现有很大差异,但其顶层接口几乎是相同的。为此,W3C基于现有的实现确定了其最小公共功能集合。
在XMLHttpRequest对象首次发布时,Microsoft还在普遍使用组件对象模型(COM)。那时,产品的可扩展性模型和应用程序都基于COM,通过COM实现组件。XMLHttpRequest自然也选择可复用的COM对象形式实现,该组件被称为Microsoft.XmlHttp。
这个COM对象是外部组件,要使其能在浏览器内运行,需要显式的给予许可。具体来说,为运行XMLHttpRequest对象,进而启用构建于该对象上的AJAX功能,客户端计算机至少要能接受“标记为可安全执行脚本的ActiveX组件”。
而有Mozilla的浏览器中,XMLHttpRequest对象成为浏览器对象模型的一部分,而不依赖于外部组件。也就是说,Mozilla浏览器中的XMLHttpRequest是通过脚本引擎发布的,而不使用这个COM组件。
这样,在各种Mozilla浏览器中,XMLHttpRequest很像是固有的JavaScript对象,可通过new运算符来实例化:
如果浏览器是IE 6.0及更低版本,XMLHttpRequest对象要通过ActiveXObject包装器来实例化:
从IE 7.0开始,XMLHttpRequest对象变成了浏览器对象。
XMLHttpRequest对象的使用
XMLHttpRequest旨在执行一项关键操作:发送HTTP请求,请求可以同步方式发送,也可以异步方式发送。下面的代码给出了该对象的编程接口:
{
function onreadystatechange;
readonly unsigned short readState;
void open(string method, string url);
void open(string method, string url, bool async);
void open(string method, string url, bool async, string user);
void open(string method, string url, bool async, string user, string pswd);
void setRequestHeader(string header, string value);
void send(string data);
void send(Document data);
void abort();
string getAllResponseHeaders();
string getResponseHeader(string header);
string responseText;
Document responseXML;
unsigned short status;
string statusText;
};
该组件的使用涉及两步操作:
1. 打开通过目标URL的信道,指定要使用的方法(如GET或POST等),确定是否要以异步方式执行。
2. 设置必要的标头,最后发送请求。如果请求的动作是POST,则将请求的主体传给send方法。
如果选择异步操作,send方法会立即返回。我们可以编写一个onreadystatechange函数,通过该函数在处理结束后检查当前操作的状态。下面的代码演示了如何通过XMLHttpRequest对象来发送POST请求:
try
{
xmlRequest = new XMLHttpRequest();
}
catch (e)
{
try
{
xmlRequest = new ActiveXObject( " Microsoft.XMLHttp " );
}
catch (e)
{
}
}
// Prepare for a synchronous POST request
var body = null ;
xmlRequest.Open( " POST " , pageUrl, false );
xmlRequest.setRequestHeader( " Content-type " , " application/x-www-urlencoded " );
xmlRequest.send(body);
在同步调用中,send方法在响应完全被下载并解析后才会返回。我们可以通过responseText属性以纯文件的形式访问响应。如果响应为XML流,则可以通过responseXml属性,以XML DOM对象的形式来使用它。