内容:摘自《锋利的jQuery》第一版 第六章
Ajax全称为 “Asynchronous Javascript and XML” (异步Javascript与XML),它并不是指一种单一的技术,而是有机的利用了一系列交互式网页应用相关的技术所形成的结合体。它的出现,揭开了无刷新更新页面的新时代,并又代替传统的Web方式和通过隐藏的框架来进行异步提交的趋势,是Web开发应用的一个里程碑。
1、Ajax的优势和不足
1.1 Ajax的优势
- 不需要插件的支持
- 优秀的用户体验
- 提高Web程序的性能
- 减轻服务器和宽带的负担
1.2 Ajax的不足
- 浏览器对XMLHttpRequest的支持不足
- 破坏浏览器前进、后退按钮的正常功能
- 对搜索引擎的支持的不足
- 开发和调试工具的缺乏
2、Ajax的XMLHttpRequest对象
Ajax的核心对象是XMLHttpRequest对象,它是Ajax实现的关键-----发送异步请求、接收响应及执行回调都是通过它来完成的。XMLHttpRequest对象最早是在 Microsoft Internet Explorer 5.0 ActiveX 组件中被引入 的,之后各大浏览器厂商都以JavaScript内置对象的方式来实现XMLHttpRequest对象。
3、编写第一个Ajax例子
在正式接触jQueryd的Ajax操作之前,先看一个传统的javascript实现的Ajax例子。例子描述:单击一个按钮,然后通过传统的Ajax的方式从服务器端取回一个“Hello Ajax!”的字符串并显示在网页上。
首先在前台页面书写HTML代码,代码如下:
<input type="button" value="Ajax提交" onclick="Ajax();" />
<div id="resText"></div>
<button>按钮触发Ajax,id为“resText”的元素用来显示从服务器返回的HTML文本。接下来的任务就是完成Ajax()函数,实现步骤如下。
(1)定义一个函数,通过该函数来异步获取信息,代码如下:
function Ajax(){
//.......
}
(2)声明一个空对象用来装入XMLHttpRequest对象,代码如下:
var xmlHttpReq = null;
(3)给XMLHttpRequest对象赋值,代码如下:
//IE5 IE6是以ActiveXObject的方式引入XMLHttpRequest对象的
if (window.ActiveXObject){
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
//除IE5 IE6以外的浏览器,XMLHttpRequest是window的对象
else if (window.XMLHttpRequest){
xmlHttpReq = new XMLHttpRequest();//实例化一个XMLHttpRequest对象
}
(4)实例化成功后,使用open()方式初始化XMLHttpRequest对象,指定HTTP方法和要使用的服务器URL,代码如下:
//调用open()方法并采用异步方式
xmlHttpReq.open("GET", "test.php", true );
默认情况下,使用XMLHttpRequst对象发送的HTTP请求是异步进行的,但是可以显示地把async参数设置为true,如上代码所示。
(5)因为要做一个异步调用,所以需要注册一个XMLHttpRequest对象将调用的回调事件处理器当它的readyState值改变时调用。当readyState值被改变时,会激发一个readystatechange事件,可以使用 onreadystatechange 属性来注册该回调事件处理器,代码如下:
//设置回调函数
xmlHttpReq.onreadystatechange=RequestCallBack;
(6)使用send()方法发送该请求,因为这个请求使用的时HTTP的GET方式,所以可以在不指定参数或使用null参数的情况下调用 send() 方法,代码如下:
//因为使用 GET 方法提交,所以可以使用 null 参数调用
xmlHttpReq.send(null);
当请求状态改变时,XMLHttpRequest对象调用 onreadystatechange 属性注册的事件处理器。因此,在处理响应之前,事件处理器因该首先检查readyState的值和HTTP的状态。当请求完成加载(readyState值为4)并且响应已经成功(HTTP状态值为200)时,就可以调用一个JavaScript函数来处理该响应内容,代码如下:
//一旦readyState值改变,将会调用该函数
function RequestCallBack(){
if (xmlHttpReq.readyState == 4) {
if (xmlHttpReq.status == 200) {
//将xmlHttpReq.responseText 的值赋予 id 为 resText 的元素
document.getElementById("resText").innerHTML = xmlHttpReq.responseText;
}
}
}
最后,如果单击 “Ajax提交” 按钮后发现网页上出现了 “Hello Ajax!”,那么就完成了第一个 Ajax 调用。
4、 jQuery中的Ajax
jQuery对Ajax操作进行了封装,在jQuery中 $.ajax() 方法属于最底层的方法,第 2 层是 load()、$.get() 和 $.post() 方法,第 3 层是 $.getScript() 和 $.getJSON() 方法。首先介绍第 2 层的方法,因为使用频率很高。
4.1 load() 方法
- 载入 HTML 文档
load() 方法是 jQuery 中最为简单和常用的Ajax方法,能载入远程HTML代码并插入DOM中。它的结构为:
load( url [, data] [, callback] )
load()方法参数解释如下表所示:
参数名称 | 类型 | 说明 |
url | String | 请求HTML页面中的URL地址 |
data(可选) | Object | 发送至服务器的 key/value 数据 |
callback(可选) | Function | 请求完成时的回调函数,无论请求成功或失败 |
构建一个HTML页面,并命名为 test.html.代码如下:
<div class="comment">
<h6>张三:</h6>
<p class="para">沙发。</p>
</div>
<div class="comment">
<h6>李四:</h6>
<p class="para">板凳。</p>
</div>
<div class="comment">
<h6>王五:</h6>
<p class="para">地板。</p>
</div>
构建一个加载远程html页面的测试页面,并添加一个按钮,用来触发Ajax事件,id 为 ‘resText’的元素用来显示追加的HTML内容,代码如下:
html部分
<input type="button" id="send" value="Ajax 获取" />
<div class="comment">已有评论:</div>
<div id="resText"></div>
js 部分
$(function(){
$("#send").click(function(){
$("#resText").load("test.html");
});
});
- 筛选载入的HTML文档
上面的例子是将 test.html 的内容都加载到 id 为 ‘resText’ 的元素里。如果只需要加载test.html页面内的某些元素,那么可以使用load()方法的URL参数来达到目的。通过URL参数指定选择符,就可以很方便的从加载过来的HTML文档里筛选出所需要的内容。
load()方法的URL参数的语法结构为: “url selector”。注意,URL与选择器之间有一个空格。
例如只需要加载test.html页面中的 class 为 “para” 的内容,可以使用如下代码来完成:
$("#resText").load("test.html .para");
- 传递方式
load() 方法的传递方式,根据参数 data 来自动指定。如果没有参数传递,则采用 GET 方式传递;反之,则自动转为 POST 方式。
//无参数传递,则是 GET 方式
$("#resText").load("test.php" , function(){
//......
});
//有参数传递,则是 POST 方式
$("#resText").load("test.php", { name : "rain", age: "22"} , function(){
//......
});
- 回调函数
对于必须在加载完成后才嗯那个继续的操作,load()方法提供了回调函数(callback),该函数有3个参数,分别代表请求返回的内容、请求状态和XMLHttpRequest对象,jQuery代码如下:
$("#resText").load("test.php" , function(responseText, textStatus, XMLHttpRequest){
// responseText : 请求返回的内容
// textStatus : 请求状态:success、error、notmodified、timeout 4 种
// XMLHttpRequest: XMLHttpRequest对象
});
在 load() 方法中,无论Ajax请求是否成功,只要请求完成(complete)后,回调函数(callback)就会被触发。对应于 $.ajax()方法中的 complete 回调函数。
4.2 $.get() 方法 和 $.post() 方法
load()方法通常用来从 Web 服务器上获取静态的数据文件,然而这边更不能体现Ajax的全部价值。在项目中,如果需要传递一些参数给服务器中的页面,那么可以使用$.get() 或者 $.post() 方法(或者是 $.ajax() 方法)
- $.get() 方法
$.get() 方法使用 GET 方式来进行异步请求。它的结构为:
$.get( url [, data] [, callback] [, type] )
$.get() 方法参数解释如下表所示:
参数名称 | 类型 | 说明 |
url | String | 请求HTML页的URL地址 |
data(可选) | Object | 发送至服务器的 key/value 数据会作为 QueryString 附加到请求URL中 |
callback(可选) | Function | 载入成功时的回调函数(只有当Response的返回状态是success才调用该方法)自动将请求结果和状态传递给该方法 |
type(可选) | String | 服务器端返回内容的格式,包括 xml、html、script、json、text 和 _default |
例子:返回 HTML 片段
由于服务器返回的数据格式是 HTML 片段,因此并不需要经过处理就可以将新的HTML数据插入到页面上。jQuery代码如下:
$(function(){
//点击提交按钮,将表单数据提交到服务器 并 接收响应的数据
$("#send").click(function(){
$.get("get1.php",{
//获取页面元素
username: $("#username").val(),
content: $("#content").val()
},
function(data, textStatus){
//将返回的数据添加到页面上
$("#resText").html(data);
}
);
});
});
例子:返回 XML 文档
由于服务器端返回的数据格式是 XML 文档,因此需要对返回的数据进行处理,处理 XML 文档与处理 HTML 文档一样,也可以使用常规的 attr()、find()、filter()以及其他方法。jQuery代码如下:
$(function(){
//点击提交按钮,将表单数据提交到服务器 并 接收响应的数据
$("#send").click(function(){
$.get("get1.php",{
//获取页面元素
username: $("#username").val(),
content: $("#content").val()
},
function(data, textStatus){
//处理XML(文档)格式数据
var username = $(data).find("comment").attr("username");
var content = $(data).find("comment").attr("content ");
var txtHtml = "<div class='comment'><h6>" + username + ":</h6><p class='para'>" + content + "</p></div>";
//将返回的数据添加到页面上
$("#resText").html(txtHtml);
}
);
});
});
由于期待服务器端返回的数据格式是 XML 文档,因此需要在服务器端色湖之 Content-Type类型,代码如下:
header("Content-Type:text/xml;chaarset=utf-8");// php 环境
例子:返回 JSON 文件
使用JSON数据格式的文件,很大程度上是因为 XML 文档体积大和难以解析。JSON文件非常简洁,也容易阅读。jQuery代码如下:
$(function(){
//点击提交按钮,将表单数据提交到服务器 并 接收响应的数据
$("#send").click(function(){
$.get("get3.php",{
//获取页面元素
username: $("#username").val(),
content: $("#content").val()
},
function(data, textStatus){
//处理JSON(文件)格式数据
var username = data.username;
var content = data.content;
var txtHtml = "<div class='comment'><h6>" + username + ":</h6><p class='para'>" + content + "</p></div>";
//将返回的数据添加到页面上
$("#resText").html(txtHtml);
},"json");
});
});
注意:JSON 的格式非常严格,构建的JSON文件必须完整无误,任何一个括号的不匹配或者缺少逗号,都会导致页面上的脚本终止运行,甚至还会带来其他更加严重的负面影响。
- $.post() 方法
它与$.get() 方法的结构和使用方式都相同,不过它们之间仍然有以下区别:
GET 请求会将参数跟在URL后面进行传递, 而POST请求则是最为HTTP消息的实体内容发送给 Web 服务器。
GET 方式对传输的数据有大小限制(通常不能大于 2 KB),而使用POST方式传递的数据量要比GET方式大得多(理论上不受限制)。
GET 方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全性问题,而POST方式相对来说就可以避免这些问题。
GET 方式和POST 方式传递的数据在服务器端的获取也不同。在PHP中,GET方式的数据可以使用$_GET[]获取,而POST方式可以使用$_POST[]获取,两种方式都可以使用$_REQUEST[]来获取。
由于POST和GET方式提交的数据都可以通过$_REQUEST[]来获取,因此只需要改变jQuery函数,就可以将程序在GET请求和POST请求之间切换。代码如下:
$(function(){
//点击提交按钮,将表单数据提交到服务器 并 接收响应的数据
$("#send").click(function(){
$.post("post1.php",{
//获取页面元素
username: $("#username").val(),
content: $("#content").val()
},
function(data, textStatus){
//将返回的数据添加到页面上
$("#resText").html(data);
}
);
});
});
另外,当load()方法带有参数传递,会使用POST方式发送请求,因此也可以使用load()方法来完成同样的功能。代码如下:
$(function(){
//点击提交按钮,将表单数据提交到服务器 并 接收响应的数据
$("#send").click(function(){
$("#resText").load("post1.php",{
//获取页面元素
username: $("#username").val(),
content: $("#content").val()
}
);
});
});
4.3 $.getScript() 方法 和 $.getJSON() 方法
- $.getScript() 方法
有时候,在页面初次加载时就取得所需要的全部 Javascript 文件是完全没有必要的。虽然可以在需要哪个 Javascript 文件时,动态地创建<script>标签,jQuery代码如下:
$(document.createElement("script")).attr("src","test.js").appendTo("head");
或者
$("<script type='text/javascript' src='test.js' />").appendTo("head");
但是这种方式并不理想。为此,jQuery提供了$.getScript()方法来直接加载 .js 文件,与加载一个 HTML 片段一样简单方便,并且不需要对 Javascript 文件进行处理,Javascript文件会自动执行。jQuery代码如下:
$(function(){
$("#send").click(function(){
$.getScript('test.js');
});
});
与其他 Ajax 方法一样,$.getScript() 方法也有回调函数,它会在 Javascript文件成功载入后运行。例如想载入jQuery官方颜色动画插件(jquery.color.js),成功后给元素绑定颜色变化动画,就可以用到$.getScript()方法的回调函数。代码如下:
$(function(){
$.getScript("http://dev.jquery.com/view/trunk/plugins/color/jquery.color.js",
function(){
$("#go").click(function(){
$(".block").animate({backgroundColor: 'pink'},1000)
.animate({backgroundColor: 'blue'},1000);
});
});
})
- $.getJSON() 方法
$.getJSON() 方法用于加载JSON文件,与$.getScript()方法的用法相同。jQuery代码如下:
$(function(){
$("#send").click(function(){
$.getJSON('test.json');
});
});
上面的代码虽然函数加载了 JSON 文件,但是斌没有告诉 JavaScript 对返回的数据如何处理。为此,jQuery提供了回调函数,在回调函数里处理返回的数据,代码如下:
$(function(){
$("#send").click(function(){
$.getJSON('test.json',function(data){
//data : 返回的数据
});
});
});
可以在函数中通过data变量来遍历响应的数据,也可以使用迭代方式为没够项构建响应的HTML代码。虽然在这里可以使用传统的for循环来实现。
jQuery也提供了一个通用的遍历方法 $.each(),可以用于遍历对象和数组。$.each()函数不同于jQuery对象的each()方法,它是一个全局函数,不操作jQuery对象,而是以一个数组或者对象作为第1个参数,以一个回调函数作为第2个参数。回调函数拥有两个参数:第1个为对象的成员或数组的索引,第2个为对应变量或内容。如果需要退出 each循环,只需要返回 false即可。
代码如下:
$(function(){
$("#send").click(function(){
$.getJSON('test.json',function(data){
//data : 返回的数据
$("#resText").empty();
var html = '';
$.each( data , function( commentIndex , comment){
html += '<div class="comment" ><h6>'
+ comment['username'] + '</h6><p class="para">'
+ comment['content'] + '</p></div>';
});
$("#resText").html(html);
});
});
});
JSONP:可以通过JSONP形式的回调函数来加载其他网站的JSON数据。JSONP是一个非官方的协议,它允许在服务器端继承Script tags返回至客户端,通过javascript Callback 的形式实现跨域访问。由于同源策略的限制,开发人员不能在外部服务器进行通信的时候使用XMLHttpRequest。而JSONP是一种可以绕过同源策略的方法,即通过使用JSON与<script>标记相结合的方法,从服务器端直接返回可执行的JavaScript函数调用或者JavaScript对象。
4.3 $.ajax() 方法
$.ajax() 方法是jQuery最底层的Ajax实现。它的结构为:$.ajax(options)
该方法直有 1 个参数,但在这个对象里包含了$.ajax()方法所需要的请求设置以及回调函数等信息,参数以 key/value 的形式存在,所在参数都是可选的,常用的参数如下表:
参数名称 | 类型 | 说明 |
url | String | (默认为当前也地址)发送请求的地址 |
type | String | 请求方式(POST或GET)默认为GET。注意其他HTTP请求方法,例如PUT 和 DELET也可以使用,但仅部分浏览器支持 |
timeout | Number | 设置请求超时时间(毫秒)。此设置将覆$.ajaxSetup()方法的全局设置 |
data | Object 或 String | 发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。GET请求中将附加在URL后。防止这种自动转换,可以查看 processData选项。对象必须为 key/value 格式,例如{foo1: "bar1",foo2: "bar2"}转换为&foo1=bar1&foo2=bar2 如果是数组,jQuery将自动为不同值对应一个名称。例如:{foo: ["bar1" , "bar2"]} 转换为 &foo=bar1&foo=bar2 |
dataType | String | 预期服务器端返回数据类型。如果不指定,jQuery将自动根据HTTP包MIME信息返回responseXML或responseText,并最为回调函数参数传递。可以的类型如下: xml:返回XML文档,可用jQuery处理。 html:返回纯文本HTML信息,宝行的script标签会在插入DOM时执行。 script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远处请求时(不再同一个域下),所有的POST请求都将转换为GET请求。 json:返回JSON数据。 jsonp:JSONP格式。使用JSONP形式的调用函数时,例如 myurl?callback=?,jQuery将自动替换后一个"?"为正确的函数名,以执行回调函数。 text:返回纯文本字符串。 |
beforeSend | Function | 发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。XMLHttpRequest对象时唯一的参数。 function (XMLHttpRequest){ this;//调用本次Ajax请求时传递的options参数 } |
complete | Function | 请求完成后调用的回调函数(请求成功或失败时均调用)。 参数:XMLHttpRequest对象和一个描述成功请求类型的字符串。 function (XMLHttpRequest, textStatus){ this;//调用本次Ajax请求时传递的options参数 } |
success | Function | 请求成功后调用的回调函数,有两个参数。 (1)由服务器返回,并根据dataType参数进行处理后的数据。 (2)描述状态的字符串。 function (data, textStatus){ // data 可能是 xmlDoc、jsonObj、html、text等 this;//调用本次Ajax请求时传递的options参数 } |
error | Function | 请求失败时被调用的回调函数,有3个参数。即 XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。 Ajax事件函数如下: function (XMLHttpRequest, textStatus, errorThrown){ //通常情况下,textStatus 和 errorThrown 只有一个包含信息。 this;//调用本次Ajax请求时传递的options参数 } |
global | Boolean | 默认为true。表示是否触发全局Ajax事件。设置为false将不会触发全局Ajax事件,ajaxStart或AjaxStop可用户控制各种Ajax事件。 |
如果需要使用$.ajax()方法来进行Ajax开发,那么上面这些常用的参数都必须了解。此外,$.ajax()方法还有其他参数。
前面的$.load()、$.get()、$.post()、$.getScript()和$.getJSON()这些方法,都是基于$.ajax()方法创建的,$.ajax()方法是jQuery最底层的Ajax实现,因此可以用它来代替前面的所有方法。
例如:使用下面的jQuery代码代替$.getScript()方法:
$(function(){
$("#send").click(function(){
$.ajax({
type: "GET",
url: "test.js",
dataType: "script"
});
});
})
例如:使用下面的jQuery代码代替$.getJSON()方法:
$(function(){
$("#send").click(function(){
$.ajax({
type: "GET",
url: "test.json",
dataType: "json",
success: function(data){
//data : 返回的数据
$("#resText").empty();
var html = '';
$.each( data , function( commentIndex , comment){
html += '<div class="comment" ><h6>'
+ comment['username'] + '</h6><p class="para">'
+ comment['content'] + '</p></div>';
});
$("#resText").html(html);
}
});
});
});
5、 jQuery中的Ajax 全局事件
方法名称 | 说明 |
ajaxStart(callback) | Ajax请求开始时执行的函数 |
ajaxStop(callback) | Ajax请求结束时执行的函数 |
ajaxComplete(callback) | Ajax请求完成时执行的函数 |
ajaxError(callback) | Ajax请求发生错误时执行的函数,捕捉到的错误可以作为最后一个参数传递 |
ajaxSend(callback) | Ajax请求发送前执行的函数 |
ajaxSuccess(callback) | Ajax请求成功时执行函数 |
如果想时某个Ajax请求部受全局方法的影响,那么可以使用$.ajax(options)方法时,将参数中的global设置为false,jQuery代码如下:
$.ajax({
url: "test.html",
global: false //不触发全局Ajax事件
})