参与人员:
发布记录:
版本
|
日期
|
作者
|
说明
|
1.0
|
<chsdate w:st="on" isrocdate="False" islunardate="False" day="28" month="10" year="2005"><span lang="EN-US" style="FONT-FAMILY: 宋体">2005-10-28</span></chsdate>
|
柯自聪
|
创建,第一版
|
|
|
|
|
链接:
OpenDoc
版权说明:
本文档版权归原作者所有。
在免费、且无任何附加条件的前提下,可在
网络媒体中
自由传播。
如需部分或者全文引用,请事先征求作者意见。
如果本文对您有些许帮助,表达谢意的最好方式,是将您发现的问题和文档改进意见及时反馈给作者。当然,倘若有时间和能力,能为技术群体无偿贡献自己的所学为最好的回馈。
AJAX
开发简略
...
1
一、AJAX
定义
...
3
二、现状与需要解决的问题
...
3
三、为什么使用AJAX
.
4
四、谁在使用AJAX
.
6
五、用AJAX
改进你的设计
...
6
例子1
:数据校验
...
7
例子2
:按需取数据—
级联菜单
...
7
例子3
:读取外部数据
...
7
六、AJAX
的缺陷
...
7
七、AJAX
开发
...
8
7.1
、AJAX
应用到的技术
...
8
A
、XMLHttpRequest
对象
...
8
B
、Javascript
.
9
C
、DOM
.
9
D
、XML
.
9
7.2
、AJAX
开发框架
...
9
A
、初始化对象并发出XMLHttpRequest
请求
...
9
B
、指定响应处理函数
...
10
C
、发出HTTP
请求
...
10
D
、处理服务器返回的信息
...
11
E
、一个初步的开发框架
...
11
7.3
、简单的示例
...
13
A
、数据校验
...
13
B
、级联菜单
...
14
参考文章:
...
16
在使用浏览器浏览网页的时候,当页面刷新很慢的时候,你的浏览器在干什么?你的屏幕内容是什么?是的,你的浏览器在等待刷新,而你的屏幕内容是一片空白,而你在屏幕前苦苦的等待浏览器的响应。开发人员为了克服这种尴尬的局面,不得不在每一个可能需要长时间等待响应的页面上增加一个
DIV
,告诉用户“系统正在处理您的请求,请稍候
……
”。
现在,有一种越来越流行越热的“老”技术,可以彻底改变这种窘迫的局面。那就是
AJAX
。如今,随着
Gmail
、
Google-maps
的应用和各种浏览器的支持,
AJAX
正逐渐吸引全世界的眼球。
AJAX
(
Asynchronous JavaScript and XML
)其实是多种技术的综合,包括
Javascript
、
XHTML
和
CSS
、
DOM
、
XML
和
XSTL
、
XMLHttpRequest
。其中:
使用
XHTML
和
CSS
标准化呈现,使用
DOM
实现动态显示和交互,使用
XML
和
XSTL
进行数据交换与处理,使用
XMLHttpRequest
对象进行异步数据读取,使用
Javascript
绑定和处理所有数据。
在
AJAX
提出之前,业界对于上述技术都只是单独的使用,没有综合使用,也是由于之前的技术需求所决定的。随着应用的广泛,
AJAX
也成为香饽饽了。
传统的
Web
应用采用同步交互过程,这种情况下,用户首先向
HTTP
服务器触发一个行为或请求的呼求。反过来,服务器执行某些任务,再向发出请求的用户返回一个
HTML
页面。这是一种不连贯的用户体验,服务器在处理请求的时候,用户多数时间处于等待的状态,屏幕内容也是一片空白。如下图:
自从采用超文本作为
Web
传输和呈现之后,我们都是采用这么一套传输方式。当负载比较小的时候,这并不会体现出有什么不妥。可是当负载比较大,响应时间要很长,
1
分钟、
2
分钟
……
数分钟的时候,这种等待就不可忍受了。严重的,超过响应时间,服务器干脆告诉你页面不可用。另外,某些时候,我只是想改变页面一小部分的数据,那为什么我必须重新加载整个页面呢?!当软件设计越来越讲究人性化的时候,这么糟糕的用户体验简直与这种原则背道而驰。为什么老是要让用户等待服务器取数据呢?至少,我们应该减少用户等待的时间。现在,除了程序设计、编码优化和服务器调优之外,还可以采用
AJAX
。
与传统的
Web
应用不同,
AJAX
采用异步交互过程。
AJAX
在用户与服务器之间引入一个中间媒介,从而消除了网络交互过程中的处理—等待—处理—等待缺点。用户的浏览器在执行任务时即装载了
AJAX
引擎。
AJAX
引擎用
JavaScript
语言编写,通常藏在一个隐藏的框架中。它负责编译用户界面及与服务器之间的交互。
AJAX
引擎允许用户与应用软件之间的交互过程异步进行,独立于用户与网络服务器间的交流。现在,可以用
Javascript
调用
AJAX
引擎来代替产生一个
HTTP
的用户动作,内存中的数据编辑、页面导航、数据校验这些不需要重新载入整个页面的需求可以交给
AJAX
来执行。
使用
AJAX
,可以为
ISP
、开发人员、终端用户带来可见的便捷:
l
减轻服务器的负担。
AJAX
的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
l
无刷新更新页面,减少用户心理和实际的等待时间。特别的,当要读取大量的数据的时候,不用像
Reload
那样出现白屏的情况,
AJAX
使用
XMLHTTP
对象发送请求并得到服务器响应,在不重新载入整个页面的情况下用
Javascript
操作
DOM
最终更新页面。所以在读取数据的过程中,用户所面对的不是白屏,是原来的页面内容(也可以加一个
Loading
的提示框让用户知道处于读取数据过程),只有当数据接收完毕之后才更新相应部分的内容。这种更新是瞬间的,用户几乎感觉不到。
l
带来更好的用户体验。
l
可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。
l
可以调用外部数据。
l
基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
l
进一步促进页面呈现和数据的分离。
在应用
AJAX
开发上面,
Google
当仁不让是表率。
Orkut
、
Gmail
、
Google Groups
、
Google Maps
、
Google Suggest
都应用了这项技术。
Amazon
的
A9.com
搜索引擎也采用了类似的技术。
微软也在积极开发更为完善的
AJAX
应用:它即将推出代号为
Atlas
的
AJAX
工具。
Atlas
的功能超越了
AJAX
本身,包括整合
Visual Studio
的调试功能。另外,新的
ASP.NET
控件将使客户端控件与服务器端代码的捆绑更为简便。
Atlas
客户脚本框架(
Atlas Clent Script Framework
)也使与网页及相关项目的交互更为便利。但
Visual Studio 2005
中并不包含此项功能。
微软最近宣布
Atlas
客户脚本框架将包含如下内容(详细资料请访问
Atlas
计划网站):
*
一个可扩展的核心框架,它添加了
JavaScript
功能:如生命同时期管理、继承管理、多点传送处理器和界面管理。
*
一个常见功能的基本类库,有丰富的字符串处理、计时器和运行任务。
*
为
HTML
附加动态行为的用户界面框架。
*
一组用来简化服务器连通和网络访问的网络堆栈。
*
一组丰富的用户界面开发控件,如:自动完成的文本框、动画和拖放。
*
处理浏览器脚本行为差异的浏览器兼容层面。
典型的,微软将
AJAX
技术应用在
MSN Space
上面。很多人一直都对
MS Space
服务感到很奇怪,当提交回复评论以后,浏览器会暂时停顿一下,然后在无刷新的情况下把我提交的评论显示出来。这个就是应用了
AJAX
的效果。试想,如果添加一个评论就要重新刷新整个页面,那可真费事。
目前,
AJAX
应用最普遍的领域是
GIS-Map
方面。
GIS
的区域搜索强调快速响应,
AJAX
的特点正好符合这种需求。
AJAX
虽然可以实现无刷新更新页面内容,但是也不是什么地方都可以用,主要应用在交互较多、频繁读数据、数据分类良好的
Web
应用中。现在,让我们举两个例子,看看如何用
AJAX
改进你的设计。
在输入
form
表单内容的时候,我们通常需要确保数据的唯一性。因此,常常在页面上提供“唯一性校验”按钮,让用户点击,打开一个校验小窗口;或者等
form
提交到服务器端,由服务器判断后在返回相应的校验信息。前者,
window.open
操作本来就是比较耗费资源的,通常由
window. showModalDialog
代替,即使这样也要弹出一个对话框;后者,需要把整个页面提交到服务器并由服务器判断校验,这个过程不仅时间长而且加重了服务器负担。而使用
AJAX
,这个校验请求可以由
XMLHttpRequest
对象发出,整个过程不需要弹出新窗口,也不需要将整个页面提交到服务器,快速又不加重服务器负担。
以前,为了避免每次对菜单的操作引起的重载页面,不采用每次调用后台的方式,而是一次性将级联菜单的所有数据全部读取出来并写入数组,然后根据用户的操作用
JavaScript
来控制它的子集项目的呈现,这样虽然解决了操作响应速度、不重载页面以及避免向服务器频繁发送请求的问题,但是如果用户不对菜单进行操作或只对菜单中的一部分进行操作的话,那读取的数据中的一部分就会成为冗余数据而浪费用户的资源,特别是在菜单结构复杂、数据量大的情况下(比如菜单有很多级、每一级菜又有上百个项目),这种弊端就更为突出。
现在应用
AJAX
,在初始化页面时我们只读出它的第一级的所有数据并显示,在用户操作一级菜单其中一项时,会通过
Ajax
向后台请求当前一级项目所属的二级子菜单的所有数据,如果再继续请求已经呈现的二级菜单中的一项时,再向后面请求所操作二级菜单项对应的所有三级菜单的所有数据,以此类推……这样,用什么就取什么、用多少就取多少,就不会有数据的冗余和浪费,减少了数据下载总量,而且更新页面时不用重载全部内容,只更新需要更新的那部分即可,相对于后台处理并重载的方式缩短了用户等待时间,也把对资源的浪费降到最低。
AJAX
可以调用外部数据,因此,可以对一些开发的数据比如
XML
文档、
RSS
文档进行二次加工,实现数据整合或者开发应用程序。
AJAX
不是完美的技术。使用
AJAX
,它的一些缺陷不得不权衡一下:
l
AJAX
大量使用了
Javascript
和
AJAX
引擎,而这个取决于浏览器的支持。
IE5.0
及以上、
Mozilla1.0
、
NetScape7
及以上版本才支持,
Mozilla
虽然也支持
AJAX
,但是提供
XMLHttpRequest
的方式不一样。所以,使用
AJAX
的程序必须测试针对各个浏览器的兼容性。
l
AJAX
更新页面内容的时候并没有刷新整个页面,因此,网页的后退功能是失效的;有的用户还经常搞不清楚现在的数据是旧的还是已经更新过的。这个就需要在明显位置提醒用户“数据已更新”。
l
对流媒体的支持没有
FLASH
、
Java Applet
好。
l
一些手持设备(如手机、
PDA
等)现在还不能很好的支持
Ajax
。
到这里,已经可以清楚的知道
AJAX
是什么,
AJAX
能做什么,
AJAX
什么地方不好。如果你觉得
AJAX
真的能给你的开发工作带来改进的话,那么继续看看怎么使用
AJAX
吧。
7.1
、
AJAX
应用到的技术
AJAX
涉及到的
7
项技术中,个人认为
Javascript
、
XMLHttpRequest
、
DOM
、
XML
比较有用。
A
、
XMLHttpRequest
对象
XMLHttpRequest
是
XMLHTTP
组件的对象,通过这个对象,
AJAX
可以像桌面应用程序一样只同服务器进行数据层面的交换,而不用每次都刷新界面,也不用每次将数据处理的工作都交给服务器来做;这样既减轻了服务器负担又加快了响应速度、缩短了用户等待的时间。
IE5.0
开始,开发人员可以在
Web
页面内部使用
XMLHTTP ActiveX
组件扩展自身的功能,不用从当前的
Web
页面导航就可以直接传输数据到服务器或者从服务器接收数据。
,Mozilla1.0
以及
NetScape7
则是创建继承
XML
的代理类
XMLHttpRequest
;对于大多数情况,
XMLHttpRequest
对象和
XMLHTTP
组件很相似,方法和属性类似,只是部分属性不同。
XMLHttpRequest
对象初始化:
<script language="”javascript”" type="text/javascript"></script>
var http_request = false;
//IE
浏览器
http_request = new ActiveXObject("Msxml2.XMLHTTP");
http_request = new ActiveXObject("Microsoft.XMLHTTP");
//Mozilla
浏览器
http_request = new XMLHttpRequest();
XMLHttpRequest
对象的方法:
方法
|
描述
|
abort()
|
停止当前请求
|
getAllResponseHeaders()
|
作为字符串返回完整的
headers
|
getResponseHeader("headerLabel")
|
作为字符串返回单个的
header
标签
|
open("method","URL"[,asyncFlag[,"userName"[, "password"]]])
|
设置未决的请求的目标
URL
,方法,和其他参数
|
send(content)
|
发送请求
|
setRequestHeader("label", "value")
|
设置
header
并和请求一起发送
|
XMLHttpRequest
对象的属性:
属性
|
描述
|
onreadystatechange
|
状态改变的事件触发器
|
readyState
|
对象状态
(integer):
0 =
未初始化
1 =
读取中
2 =
已读取
3 =
交互中
4 =
完成
|
responseText
|
服务器进程返回数据的文本版本
|
responseXML
|
服务器进程返回数据的兼容
DOM
的
XML
文档对象
|
status
|
服务器返回的状态码
,
如:
404 = "
文件未找到
"
、
200 ="
成功
"
|
statusText
|
服务器返回的状态文本信息
|
B
、
Javascript
Javascript
一直被定位为客户端的脚本语言,应用最多的地方是表单数据的校验。现在,可以通过
Javascript
操作
XMLHttpRequest
,来跟数据库打交道。
C
、
DOM
DOM
(
Document Object Model
)是提供给
HTML
和
XML
使用的一组
API
,提供了文件的表述结构,并可以利用它改变其中的内容和可见物。脚本语言通过
DOM
才可以跟页面进行交互。
Web
开发人员可操作及建立文件的属性、方法以及事件都以对象来展现。比如,
document
就代表页面对象本身。
D
、
XML
通过
XML
(
Extensible Markup Language
),可以规范的定义结构化数据,是网上传输的数据和文档符合统一的标准。用
XML
表述的数据和文档,可以很容易的让所有程序共享。
7.2
、
AJAX
开发框架
这里,我们通过一步步的解析,来形成一个发送和接收
XMLHttpRequest
请求的程序框架。
AJAX
实质上也是遵循
Request/Server
模式,所以这个框架基本的流程也是:对象初始化
à
发送请求
à
服务器接收
à
服务器返回
à
客户端接收
à
修改客户端页面内容。只不过这个过程是异步的。
A
、初始化对象并发出
XMLHttpRequest
请求
为了让
Javascript
可以向服务器发送
HTTP
请求,必须使用
XMLHttpRequest
对象。使用之前,要先将
XMLHttpRequest
对象实例化。之前说过,各个浏览器对这个实例化过程实现不同。
IE
以
ActiveX
控件的形式提供,而
Mozilla
等浏览器则直接以
XMLHttpRequest
类的形式提供。为了让编写的程序能够跨浏览器运行,要这样写:
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
有些版本的
Mozilla
浏览器处理服务器返回的未包含
XML mime-type
头部信息的内容时会出错。因此,要确保返回的内容包含
text/xml
信息。
http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');
B
、指定响应处理函数
接下来要指定当服务器返回信息时客户端的处理方式。只要将相应的处理函数名称赋给
XMLHttpRequest
对象的
onreadystatechange
属性就可以了。比如:
http_request.onreadystatechange = processRequest;
需要指出的时,这个函数名称不加括号,不指定参数。也可以用
Javascript
即时定义函数的方式定义响应函数。比如:
http_request.onreadystatechange = function() {
};
C
、发出
HTTP
请求
指定响应处理函数之后,就可以向服务器发出
HTTP
请求了。这一步调用
XMLHttpRequest
对象的
open
和
send
方法。
http_request.open('GET', 'http://www.example.org/some.file', true);
http_request.send(null);
open
的第一个参数是
HTTP
请求的方法,为
Get
、
Post
或者
Head
。
第二个参数是目标
URL
。基于安全考虑,这个
URL
只能是同网域的,否则会提示“没有权限”的错误。这个
URL
可以是任何的
URL
,包括需要服务器解释执行的页面,不仅仅是静态页面。
第三个参数只是指定在等待服务器返回信息的时间内是否继续执行下面的代码。如果为
True
,则不会继续执行,直到服务器返回信息。默认为
True
。
按照顺序,
open
调用完毕之后要调用
send
方法。
send
的参数如果是以
Post
方式发出的话,可以是任何想传给服务器的内容。不过,跟
form
一样,如果要传文件给服务器,必须先调用
setRequestHeader
方法,修改
MIME
类别。如下:
http_request.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);
D
、处理服务器返回的信息
在第二步我们已经指定了响应处理函数,这一步,来看看这个响应处理函数都应该做什么。
首先,它要检查
XMLHttpRequest
对象的
readyState
值,判断请求目前的状态。参照前文的属性表可以知道,
readyState
值为
4
的时候,代表服务器已经传回所有的信息,可以开始处理信息并更新页面内容了。如下:
if (http_request.readyState == 4) {
//
信息已经返回,可以开始处理
} else {
//
信息还没有返回,等待
}
服务器返回信息后,还需要判断返回的
HTTP
状态码,确定返回的页面没有错误。所有的状态码都可以在
W3C
的官方网站上查到。其中,
200
代表页面正常。
if (http_request.status == 200) {
//
页面正常,可以开始处理信息
} else {
//
页面有问题
}
XMLHttpRequest
对成功返回的信息有两种处理方式:
responseText
:将传回的信息当字符串使用;
responseXML
:将传回的信息当
XML
文档使用,可以用
DOM
处理。
E
、一个初步的开发框架
总结上面的步骤,我们整理出一个初步的可用的开发框架,供以后调用;这里,将服务器返回的信息用
window.alert
以字符串的形式显示出来:
<script language="javascript">
var http_request = false;
function send_request(url) {//
初始化、指定处理函数、发送请求的函数
http_request = false;
//
开始初始化
XMLHttpRequest
对象
if(window.XMLHttpRequest) { //Mozilla
浏览器
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {//
设置
MiME
类别
http_request.overrideMimeType("text/xml");
}
}
else if (window.ActiveXObject) { // IE
浏览器
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) { //
异常,创建对象实例失败
window.alert("
不能创建
XMLHttpRequest
对象实例
.");
return false;
}
http_request.onreadystatechange = processRequest;
//
确定发送请求的方式和
URL
以及是否同步执行下段代码
http_request.open("GET", url, true);
http_request.send(null);
}
//
处理返回信息的函数
function processRequest() {
if (http_request.readyState == 4) { //
判断对象状态
if (http_request.status == 200) { //
信息已经成功返回,开始处理信息
alert(http_request.responseText);
} else { //
页面不正常
alert("
您所请求的页面有异常。
");
}
}
}
</script>
<script language="javascript" type="text/javascript"></script>
var http_request = false;
function send_request(url) {//
初始化、指定处理函数、发送请求的函数
http_request = false;
//
开始初始化
XMLHttpRequest
对象
if(window.XMLHttpRequest) { //Mozilla
浏览器
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {//
设置
MiME
类别
http_request.overrideMimeType("text/xml");
}
}
else if (window.ActiveXObject) { // IE
浏览器
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) { //
异常,创建对象实例失败
window.alert("
不能创建
XMLHttpRequest
对象实例
.");
return false;
}
http_request.onreadystatechange = processRequest;
//
确定发送请求的方式和
URL
以及是否同步执行下段代码
http_request.open("GET", url, true);
http_request.send(null);
}
//
处理返回信息的函数
function processRequest() {
if (http_request.readyState == 4) { //
判断对象状态
if (http_request.status == 200) { //
信息已经成功返回,开始处理信息
alert(http_request.responseText);
} else { //
页面不正常
alert("
您所请求的页面有异常。
");
}
}
}
7.3
、简单的示例
接下来,我们利用上面的开发框架来做两个简单的应用。
A
、数据校验
在用户注册的表单中,经常碰到要检验待注册的用户名是否唯一。传统的做法是采用
window.open
的弹出窗口,或者
window. showModalDialog
的对话框。不过,这两个都需要打开窗口。采用
AJAX
后,采用异步方式直接将参数提交到服务器,用
window.alert
将服务器返回的校验信息显示出来。代码如下:
在
之间增加一段
form
表单代码:
在开发框架的基础上再增加一个调用函数:
function userCheck() {
var f = document.form1;
var username = f.username.value;
if(username=="") {
window.alert("
用户名不能为空。
");
f.username.focus();
return false;
}
else {
send_request('sample1_2.jsp?username='+username);
}
}
看看
sample1_2.jsp
做了什么:
<%@ page contentType="text/html; charset=gb2312" errorPage="" %>
<%
String username = request.getParameter("username");
if("educhina".equals(username)) out.print("
用户名已经被注册,请更换一个用户名。
");
else out.print("
用户名尚未被使用,您可以继续。
");
%>
运行一下,嗯,没有弹出窗口,没有页面刷新,跟预想的效果一样。如果需要的话,可以在
sample1_2.jsp
中实现更复杂的功能。最后,只要将反馈信息打印出来就可以了。
B
、级联菜单
我们在第五部分提到利用
AJAX
改进级联菜单的设计。接下来,我们就演示一下如何“按需取数据”。
首先,在
<body></body>
中间增加如下
HTML
代码:
<table width="200" border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="20">
<a href="javascript:void(0)" onClick="showRoles('pos_1')">
经理室
</a>
</td>
</tr>
<tr style="display:none">
<td height="20" id="pos_1"> </td>
</tr>
<tr>
<td height="20">
<a href="javascript:void(0)" onClick="showRoles('pos_2')">
开发部
</a>
</td>
</tr>
<tr style="display:none ">
<td id="pos_2" height="20"> </td>
</tr>
</table>
在框架的基础上增加一个响应函数
showRoles(obj)
:
//
显示部门下的岗位
function showRoles(obj) {
document.getElementById(obj).parentNode.style.display = "";
document.getElementById(obj).innerHTML = "
正在读取数据
..."
currentPos = obj;
send_request("sample2_2.jsp?playPos="+obj);
}
修改框架的
processRequest
函数:
//
处理返回信息的函数
function processRequest() {
if (http_request.readyState == 4) { //
判断对象状态
if (http_request.status == 200) { //
信息已经成功返回,开始处理信息
document.getElementById(currentPos).innerHTML = http_request.responseText;
} else { //
页面不正常
alert("
您所请求的页面有异常。
");
}
}
}
最后就是
smaple2_2.jsp
了:
<%@ page contentType="text/html; charset=gb2312" errorPage="" %>
<%
String playPos = request.getParameter("playPos");
if("pos_1".equals(playPos))
out.print("
总经理
<br>
副总经理
");
else if("pos_2".equals(playPos))
out.println("
总工程师
<br>
软件工程师
");
%>
运行一下看看效果:
[转]AJAX开发简略