AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
$ w+ y! m V3 y$ D2 m
% A2 X5 S0 @+ W; u9 Q& O Ajax(Asynchronous JavaScript + XML)的定义
$ t& q) L) ?9 b' Z- _
0 r7 E2 L' Y: a7 P8 t
基于web标准(standards-based presentation)XHTML+CSS的表示;
" \+ s `* x% Q9 V2 Y5 }
) n2 e+ t( R0 v4 L
使用 DOM(Document Object Model)进行动态显示及交互;
( S) T. Y" X/ L9 x8 U
, }6 E3 p9 |1 `' s- {0 U: R- K9 g
使用 XML 和 XSLT 进行数据交换及相关操作;
5 q. e6 Z+ @6 ?: t, B- A; A/ e% M. H2 k
$ P7 X9 o- M% j
使用 XMLHttpRequest 进行异步数据查询、检索;
6 j2 e. H9 g7 f1 h6 V( W" s3 W
$ u: z4 u/ {; o# B h9 e 使用 JavaScript 将所有的东西绑定在一起。
+ Z0 t0 U! ~2 S' o6 l$ d( }7 @
9 Q/ o: Y {9 C+ Z 英文参见Ajax的提出者Jesse James Garrett的原文。
+ t3 _" {0 |! V. Z
* z3 D% w8 w5 s# @* U 类似于DHTML或LAMP,AJAX不是指一种单一的技术,而是有机地利用了一系列相关的技术。事实上,一些基于AJAX的“派生/合成”式(derivative/composite)的技术正在出现,如“AFLAX”。
( B2 a. ~$ i/ S, `5 D
2 m# C- l# T1 T7 \, W+ p AJAX的应用使用支持以上技术的web浏览器作为运行平台。这些浏览器目前包括:Mozilla、Firefox、Internet Explorer、Opera、Konqueror及Safari。但是Opera不支持XSL格式对象,也不支持XSLT。
1 Y# k M7 I, h" }
. k4 j( b/ Z; k
% U w1 ?1 y, s& g, l
与传统的web应用比较
4 ?9 Q5 _: \$ O% p
2 T, b( E0 \% _; q5 V* _- X6 v4 Y) ] 传统的web应用允许用户填写表单(form),当提交表单时就向web服务器发送一个请求。服务器接收并处理传来的表单,然後返回一个新的网页。这个做法浪费了许多带宽,因为在前後两个页面中的大部分HTML代码往往是相同的。由于每次应用的交互都需要向服务器发送请求,应用的响应时间就依赖于服务器的响应时间。这导致了用户界面的响应比本地应用慢得多。
7 i' X% R/ A; e$ c- ?4 Z, c3 M, ~; M
与此不同,AJAX应用可以仅向服务器发送并取回必需的数据,它使用SOAP或其它一些基于XML的web service接口,并在客户端采用JavaScript处理来自服务器的响应。因为在服务器和浏览器之间交换的数据大量减少,结果我们就能看到响应更快的应用。同时很多的处理工作可以在发出请求的客户端机器上完成,所以Web服务器的处理时间也减少了。
) ^3 [4 r, p" l" `1 N$ s
- _: q1 A$ m8 G Ajax应用程序的优势在于:
: {3 P2 G8 O6 z/ U \! a' h F: G5 |; ]$ a l! {' I3 |
1. 通过异步模式,提升了用户体验
# m0 n- r# f' P3 H8 O, h9 d
, {% ^" a8 A2 C) \# J9 M
2. 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
4 o" t. P( l; R0 X. o
9 r/ x' i8 ]7 M 3. Ajax引擎在客户端运行,承担了一部分本来由服务器承担的工作,从而减少了大用户量下的服务器负载。
9 F0 [) _1 S1 f) h
& o$ Q& a0 [( a, r5 o1 F. _
8 l6 F5 a+ D* w* K. C; q Ajax的工作原理
9 s& R8 X9 V& ^3 U# Y
6 `8 s4 r7 Z; E) k" r& X; B- q
Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入,它是一种支持异步请求的技术。简而言之,XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。
$ w1 d; ^6 M1 X9 }( W# Y* h( c# {' ~7 m
在创建Web站点时,在客户端执行屏幕更新为用户提供了很大的灵活性。下面是使用Ajax可以完成的功能:
: @: r( a0 T" q9 Z3 p O
1 p5 M& r* q( |- f+ `* }" `
动态更新购物车的物品总数,无需用户单击Update并等待服务器重新发送整个页面。
: u; F( L2 t) e" `5 S5 M
& }/ l4 f! j$ R/ E3 O( e 提升站点的性能,这是通过减少从服务器下载的数据量而实现的。例如,在某购物车页面,当更新篮子中的一项物品的数量时,会重新载入整个页面,这必须下载整个页面的数据。如果使用Ajax计算新的总量,服务器只会返回新的总量值,因此所需的带宽仅为原来的百分之一。 消除了每次用户输入时的页面刷新。例如,在Ajax中,如果用户在分页列表上单击Next,则服务器数据只刷新列表而不是整个页面。
2 E; r. a; y7 ^3 U% U6 F" k6 G
0 D' `+ D+ b s
直接编辑表格数据,而不是要求用户导航到新的页面来编辑数据。对于Ajax,当用户单击Edit时,可以将静态表格刷新为内容可编辑的表格。用户单击Done之后,就可以发出一个Ajax请求来更新服务器,并刷新表格,使其包含静态、只读的数据。
# M* [) _4 t9 f I
; {8 h; X" W; d' }; h/ P0 R) K$ b 一切皆有可能!但愿它能够激发您开始开发自己的基于Ajax的站点。然而,在开始之前,让我们介绍一个现有的Web站点,它遵循传统的提交/等待/重新显示的范例,我们还将讨论Ajax如何提升用户体验。
4 |6 f+ t' s. V4 J: u
' N3 p; O, V* J. I! Z# l% m Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。这样把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担,从而达到节约ISP的空间及带宽租用成本的目的。
l; Q* Z% l. R4 {5 G) ]9 r
% s+ J1 {: b9 z; e* c 我们以两个验证通行证帐号是否存在的例子来讲述AJAX在实际中的应用:
' Z/ v) H. s1 @3 F+ i! a. b9 l3 W& M/ s2 `, I3 z/ d
(1)用文本字符串的方式返回服务器的响应来验证网易通行证帐号是否存在;
8 k. W9 l( W. T4 G5 R, }9 c& w" k: q3 T
(2)以XMLDocument对象方式返回响应来验证金山通行证帐号是否存在;
. H7 `* N( G L: s$ c
6 b3 E2 v. X, T, l# l 首先,我们需要用JavaScript来创建XMLHttpRequest 类向服务器发送一个HTTP请求, XMLHttpRequest 类首先由Internet Explorer以ActiveX对象引入,被称为XMLHTTP。 后来Mozilla﹑Netscape﹑Safari 和其他浏览器也提供了XMLHttpRequest类,不过它们创建XMLHttpRequest类的方法不同。
6 W8 t( S' o" I. }) M
3 i" x, J: o' |, `- e
对于Internet Explorer浏览器,创建XMLHttpRequest 方法如下:
复制内容到剪贴板
代码:
xmlhttp_request = new ActiveXObject("Msxml2.XMLHTTP.3.0"); //3.0或4.0, 5.0
xmlhttp_request = new ActiveXObject("Msxml2.XMLHTTP");
xmlhttp_request = new ActiveXObject("Microsoft.XMLHTTP"); 由于在不同Internet Explorer浏览器中XMLHTTP版本可能不一致,为了更好的兼容不同版本的Internet Explorer浏览器,因此我们需要根据不同版本的Internet Explorer浏览器来创建XMLHttpRequest类,上面代码就是根据不同的Internet Explorer浏览器创建XMLHttpRequest类的方法。
8 ?' a' ?# f6 ]' A+ T u8 R
! ?! K5 k6 \7 _2 | 对于Mozilla﹑Netscape﹑Safari等浏览器,创建XMLHttpRequest 方法如下:
复制内容到剪贴板
代码:
xmlhttp_request = new XMLHttpRequest(); 如果服务器的响应没有XML mime-type header,某些Mozilla浏览器可能无法正常工作。 为了解决这个问题,如果服务器响应的header不是text/xml,可以调用其它方法修改该header。
复制内容到剪贴板
代码:
xmlhttp_request = new XMLHttpRequest();
xmlhttp_request.overrideMimeType('text/xml'); 在实际应用中,为了兼容多种不同版本的浏览器,一般将创建XMLHttpRequest类的方法写成如下形式:
复制内容到剪贴板
代码:
try{
if( window.ActiveXObject ){
for( var i = 5; i; i-- ){
try{
if( i == 2 ){
xmlhttp_request = new ActiveXObject( "Microsoft.XMLHTTP" ); }
else{
xmlhttp_request = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" ); }
xmlhttp_request.setRequestHeader("Content-Type","text/xml");
xmlhttp_request.setRequestHeader("Content-Type","gb2312");
break;}
catch(e){
xmlhttp_request = false; } } }
else if( window.XMLHttpRequest )
{ xmlhttp_request = new XMLHttpRequest();
if (xmlhttp_request.overrideMimeType)
{ xmlhttp_request.overrideMimeType('text/xml'); } } }
catch(e){ xmlhttp_request = false; } 在定义了如何处理响应后,就要发送请求了。可以调用HTTP请求类的open()和send()方法,如下所示:
复制内容到剪贴板
代码:
xmlhttp_request.open('GET', URL, true);
xmlhttp_request.send(null); open()的第一个参数是HTTP请求方式—GET,POST或任何服务器所支持的您想调用的方式。 按照HTTP规范,该参数要大写;否则,某些浏览器(如Firefox)可能无法处理请求。
5 z3 Q" b/ v% V+ Q% p! Q6 F- T3 _* o* N5 l
第二个参数是请求页面的URL。
# I1 g2 Q3 _1 \ Y8 m3 F# L
f* a7 s, y( a2 e7 S b2 r9 E 第三个参数设置请求是否为异步模式。如果是TRUE,JavaScript函数将继续执行,而不等待服务器响应。这就是"AJAX"中的"A"。
& z4 N; |' P: I* b5 }$ C4 G/ a& D9 g/ T& I6 S% j+ |% u. a
用JavaScript来创建XMLHttpRequest 类向服务器发送一个HTTP请求后,接下来要决定当收到服务器的响应后,需要做什么。这需要告诉HTTP请求对象用哪一个JavaScript函数处理这个响应。可以将对象的onreadystatechange属性设置为要使用的JavaScript的函数名,如下所示:
复制内容到剪贴板
代码:
xmlhttp_request.onreadystatechange =FunctionName; FunctionName是用JavaScript创建的函数名,注意不要写成FunctionName(),当然我们也可以直接将JavaScript代码创建在onreadystatechange之后,例如:
复制内容到剪贴板
代码:
xmlhttp_request.onreadystatechange = function(){
// JavaScript代码段
}; 首先要检查请求的状态。只有当一个完整的服务器响应已经收到了,函数才可以处理该响应。XMLHttpRequest 提供了readyState属性来对服务器响应进行判断。
- B: S( S' D! A5 t, M& |) c
/ @1 ^1 i- @. N( U& Z2 i4 L7 a& ? readyState的取值如下:
/ d0 w* E7 Q# ~8 x; {2 O
1 b) o) p1 S) J' }' V+ P7 Y 0 (未初始化)
( j, ^3 U7 `# V. E% s/ h9 _7 h
* l3 m+ M% p8 y" S 1 (正在装载)
/ ^% Z2 E. n: j0 ?5 @# Z
7 B; e4 `0 |4 P2 B 2 (装载完毕)
1 z- J4 [- u% h3 v: e' N+ M- {' x+ i, W: M7 b
3 (交互中)
) m: f( Y* y! V3 l1 I; J5 F( U5 P
' q, ]+ |4 ?$ V1 t% b 4 (完成)
) u* i- C. ~( a' `8 A+ V
3 z2 T) [" @% z1 f" p6 e 所以只有当readyState=4时,一个完整的服务器响应已经收到了,函数才可以处理该响应。具体代码如下:
复制内容到剪贴板
代码:
if (http_request.readyState == 4) { // 收到完整的服务器响应 }
else { // 没有收到完整的服务器响应 } 当readyState=4时,一个完整的服务器响应已经收到了,接着,函数会检查HTTP服务器响应的状态值。完整的状态取值可参见W3C文档。当HTTP服务器响应的值为200时,表示状态正常。
2 a5 e7 y2 N, c l$ f' }2 I9 J4 l* @
6 ~4 Q$ U( x5 h2 ~& w5 ~" L! x" i! D 在检查完请求的状态值和响应的HTTP状态值后,就可以处理从服务器得到的数据了。有两种方式可以得到这些数据:
! ]9 |$ k! F' }7 k
9 t) Z+ H3 m" N2 Z4 Q" R. J (1) 以文本字符串的方式返回服务器的响应
6 p) S3 E6 X* j0 C2 U# \
! s, x7 k% F& r& b9 ]# {8 {
(2) 以XMLDocument对象方式返回响应
% O$ @6 f0 b9 x# i' |
^* N% u5 P6 m k7 [ 实例一: 用文本字符串的方式返回服务器的响应来验证网易通行证帐号是否存在
7 Q) p+ P- d. e1 j, D( c! G! r/ n7 r& w. I. a) ^
首先,我们登陆网易通行证注册页面,可以看到检测用户名是否存在是将用户名提交给checkssn.jsp页面进行判断,格式为:
2 u2 N/ X, Y8 N; {7 c. ?. H* B) v" E) v- N5 C* z T
reg.163.com/register/checkssn.jsp?username=用户名
4 L: d. D: Z( i2 E- a5 }) T1 |0 S% D3 b0 g
根据上面讲到的方法,我们可以利用AJAX技术对网易通行证用户名进行检测:
2 G1 y- p* U* U8 [
. N( z1 d1 u9 g n 第一步:新建一个基于Xhtml标准的网页,在区域插入Javascript函数如下:
复制内容到剪贴板
代码:
function getXMLRequester( )
{ var xmlhttp_request = false;
try
{ if( window.ActiveXObject )
{ for( var i = 5; i; i-- ){
try{
if( i == 2 )
{ xmlhttp_request = new ActiveXObject( "Microsoft.XMLHTTP" ); }
else
{ xmlhttp_request = new ActiveXObject
( "Msxml2.XMLHTTP." + i + ".0" );
xmlhttp_request.setRequestHeader("Content-Type","text/xml");
xmlhttp_request.setRequestHeader("Content-Type","gb2312"); }
break;}
catch(e){ xmlhttp_request = false; } } }
else if( window.XMLHttpRequest )
{ xmlhttp_request = new XMLHttpRequest();
if (xmlhttp_request.overrideMimeType)
{ xmlhttp_request.overrideMimeType('text/xml'); } } }
catch(e){ xmlhttp_request = false; }
return xmlhttp_request ; }
function IDRequest(n) { //定义收到服务器的响应后需要执行的JavaScript函数
url=n+document.getElementById('163id').value;//定义网址参数
xmlhttp_request=getXMLRequester();//调用创建XMLHttpRequest的函数
xmlhttp_request.onreadystatechange = doContents;//调用doContents函数
xmlhttp_request.open('GET', url, true);
xmlhttp_request.send(null); }
function doContents()
{ if (xmlhttp_request.readyState == 4) {// 收到完整的服务器响应
if (xmlhttp_request.status == 200) {//HTTP服务器响应的值OK
document.getElementById('message').innerHTML = xmlhttp_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域 }
else { alert(http_request.status); } } } 在区域建立一个文本框,id为163id,再建一个id为messsge的空白区域用来显示返回字符串(也可以通过Javascript函数截取一部分字符串显示):
复制内容到剪贴板
代码:
<input type=text id="163id">
<span id="message"></span> 这样,一个基于AJAX技术的用户名检测页面就做好了,不过这个页面将返回服务器响应生成页面的所有字符串,当然还可以对返回的字符串进行一些操作,便于应用到不同的需要当中。
# h: U, y" b6 p) Y9 u6 d
2 f) V% t2 p, g6 K" Y+ p 实例二: 以XMLDocument对象方式返回响应来验证金山通行证帐号是否存在
! B5 f! p2 ~1 w, N3 P+ ^5 k5 z* g5 Y, c1 p
在上面的例子中,当服务器对HTTP请求的响应被收到后,我们会调用请求对象的reponseText属性。该属性包含了服务器返回响应文件的内容。现在我们以XMLDocument对象方式返回响应,此时将不再需要reponseText属性而使用responseXML属性。
: E6 I! Z( O* q
+ s; K8 p1 m6 Q. j# N 首先登陆金山通行证注册页面,我们发现金山通行证用户名的检测方式为: pass.kingsoft.com/ksgweb/jsp/login/uid.jsp?uid=用户名,并且返回XML数据:
9 Q: u* t+ E j$ |4 @
/ z1 l) T8 v* f* }* W4 `) D% O isExistedUid -2
+ ^( `5 F3 M3 ~: b
; a! c4 l- z# n( g, t7 j 当result值为-1时表示此用户名已被注册,当result值为-2时表示此用户名尚未注册,因此通过对result值的判断可以知道用户名是否被注册。
! W1 j4 Z# `' ^8 A
5 @; P6 w# u1 c( N" C" u
对上例代码进行修改:
! i2 N. f+ f0 ^8 o1 `" B
/ ]# O2 p3 f) `, |! o
首先找到
复制内容到剪贴板
代码:
document.getElementById('message').innerHTML = xmlhttp_request.responseText; 改为:
复制内容到剪贴板
代码:
var response = xmlhttp_request.responseXML.documentElement;
var result = response.getElementsByTagName('result')[0].firstChild.data;//返回result节点数据
if(result ==-2){
document.getElementById('message').innerHTML = "用户名"+document.getElementById('163id').value+"尚未注册";}
else if(result ==-1){
document.getElementById('message').innerHTML = "对不起,用户名"+document.getElementById('163id').value+"已经注册";} 通过以上两个实例说明了AJAX的客户端基础应用,采用的是网易和金山现成的服务器端程序,当然为了开发合适自己页面的程序,还需要对自己编写服务器端程序,这设计到程序语言及数据库的操作,对于有一定程序基础的读者一定不是很难的事情。