传统的网页需要通过重新加载来更新它的内容。此种方式非常的低效,服务器不得不重构整个页面,之后再发送所有的 HTML CSS JavaScript 到用户端。2003年之后,大部分主流浏览器,通过 XMLHttpRequest(XHR) 对象来解决这个问题,允许浏览器同服务器进行通信,而无需重新加载页面。
XMLHttpRequest 对象是 Ajax(Asynchronous JavaScript and XML) 技术的一部分。Ajax 请求由 JavaScript 触发,发送请求至某个 URL,当接收到响应时,一个回调函数会被触发来处理此响应。由于请求是异步的,所以余下的代码可以继续执行。
不幸的是,不同的浏览器通过不同的方式执行 Ajax API。幸运的是 jQuery 提供 Ajax 支持,来消除各个浏览器之间的差异;它提供全功能的 $.ajax() 方法,和其他简单便捷的方法,例如:$.get() $.getScript() $.getJSON() $.post() $().load()
大多数 jQuery 应用程式不使用 XML 来传递数据,而是通过原始的 HTML 或者 JSON(JavaScript Object Notation) 来传递数据。
一般来说,Ajax 不能跨网域工作。example1.com 不能发送 Ajax 请求至 example2.com。解决方案:JSONP (JSON with Padding) 使用 <script> 标签,从另一个域加载包含任一 JavaScript 内容和 JSON 的文件。更多的浏览器已经使用一种称为 Cross-Origin Resource Sharing (CORS) 的技术,来允许 Ajax 请求不同的网域。
Key Concepts 关键概念
GET vs POST
用于向服务器发送请求的最常见的两种方法是:GET 和 POST。
GET 方法应当用于非破坏性的操作。指该操作仅仅从服务端获取数据,不改变服务端的数据。浏览器可能会缓存 GET 请求。GET 请求通常在查询字符串中发送它所有的数据。
POST 方法用于破坏性的操作。指该操作会改变服务端的数据。POST 通常不会被浏览器缓存;查询字符串可以作为 URL 的一部分,但是数据往往作为发布数据单独发送。
Data Types
jQuery 需要一些指令来设置,需要从 Ajax 请求中取得的数据的数据类型。
text 用于传输简单字符串。
html 用于传输要放置在页面上的 HTML 块。
script 用于向页面添加新脚本。
json 用于传输 JSON 格式的数据;其中可以包含字符串、数组、对象。
jsonp 用于从另一个网域传输 JSON 数据。
xml 用于传输在自定义 XML 架构中的数据。
Asynchronous 异步性
由于请求是异步的,所以请求的响应只能通过回调函数处理。示例:
var response;
$.get( "foo.php", function( r ) {
response = r;
});
console.log( response ); // undefined
$.get( "foo.php", function( response ) {
console.log( response ); // server response
});
Same-Origin Policy(同源政策) and JSONP
通常,Ajax 请求仅限于与发出请求的页面相同的协议(http 或 https);相同的端口和相同的网域。此限制不适用于通过 jQuery 的 Ajax 方法加载的脚本。注意:IE10以下版本的浏览器不支持 cross-domain AJAX 请求。
另一个例外是针对另一个网域上的 JSONP 服务的请求。在 JSONP 的情况下,服务提供者同意使用脚本来响应请求,该脚本使用 <script> 标签来载入请求页面,以此方式来避免同源的限制;该脚本将包含请求的数据。
jQuery's Ajax-Related Methods
$.ajax()
提供 configuration 对象包含完成请求所需的所有操作指南;提供请求成功或失败之后的回调函数。完整文档:jQuery.ajax
// Using the core $.ajax() method
$.ajax({
// The URL for the request
url: "post.php",
// The data to send (will be converted to a query string)
data: {
id: 123
},
// Whether this is a POST or GET request
type: "GET",
// The type of data we expect back
dataType : "json",
})
// Code to run if the request succeeds (is done);
// The response is passed to the function
.done(function( json ) {
$( "<h1>" ).text( json.title ).appendTo( "body" );
$( "<div class=\"content\">").html( json.html ).appendTo( "body" );
})
// Code to run if the request fails; the raw request and
// status codes are passed to the function
.fail(function( xhr, status, errorThrown ) {
alert( "Sorry, there was a problem!" );
console.log( "Error: " + errorThrown );
console.log( "Status: " + status );
console.dir( xhr );
})
// Code to run regardless of success or failure;
.always(function( xhr, status ) {
alert( "The request is complete!" );
});
注意:dataType 的设置,若该设置同服务端返回的数据类型不同,请求会失败。
$.ajax Options
async 默认值为:true。若设置为:false 表示该请求为同步请求,若设置为同步请求,该请求会阻塞后续代码的执行,直到该请求接收到响应。
cache 是否使用缓存响应(若可用)。默认值为:true;除了 dataType 为:script jsonp。若设置为:false,URL 会附加一个 cachebusting 参数。
done 请求成功的回调函数。该回调函数会接收响应的数据,以及请求的文本状态和未加工的请求对象。
fail 请求结果出错后调用的回调函数。该函数会接收请求的未加工的请求对象和请求的文本状态。
always 请求执行完成之后调用的回调函数,无论请求成功或失败。该函数会接收请求的未加工的请求对象和请求的文本状态。
context 回调函数执行的范围。默认情况下,回调函数中的 this 指向起初传入 $.ajax() 中的对象。
data 发送至服务端的数据。可以是对象或查询字符创(foo=bar&baz=bin)。
dataType 期望服务端返回的数据类型。若未指定,默认类型为 MIME 类型。
jsonp 要发送 jsonp 请求时,要在查询字符串中发送的回调函数名称。
timeout 设定请求等待的超时时间,单位:毫秒。
traditional 设置为:true 以使用 jQuery 1.4 版本之前的参数序列化样式。完整文档:jQuery.param
type 请求的类型:GET 或 POST;默认为:GET。其他类型如:PUT DELETE,但是可能不是所有的浏览器都支持。
url 请求的 URL。
url 属性是 $.ajax() 方法的 configuration 对象所必须的属性,其他都是可选属性。
Convenience Methods 便捷方法
$.get 发送 GET 请求至提供的 URL。
$.post 发送 POST 请求至提供的 URL。
$.getScript 在页面加入脚本。
$.getJSON 发送 GET 请求,并期望服务端返回 JSON 格式数据。
以上便捷方法,都采用一下参数:
url 请求的 URL;必须参数。
data 发送至服务端的数据;可选参数。可以为对象或查询字符创。注意:该参数对 $.getScript 不是有效的。
success callback 请求成功之后调用的回调函数;可选参数。回调函数接收响应的数据(若数据类型为:JSON,会将其转换为:JavaScript 对象),以及请求的文本状态和未加工的请求对象。
data type 期望服务端返回的数据类型;可选参数。
// Using jQuery's Ajax convenience methods
// Get plain text or HTML
$.get( "/users.php", {
userId: 1234
}, function( resp ) {
console.log( resp ); // server response
});
// Add a script to the page, then run a function defined in it
$.getScript( "/static/js/myScript.js", function() {
functionFromMyScript();
});
// Get JSON-formatted data from the server
$.getJSON( "/details.php", function( resp ) {
// Log each key in the response data
$.each( resp, function( key, value ) {
console.log( key + " : " + value );
});
});
$.fn.load
.load() 方法在 jQuery's Ajax 中是惟一的,因为它在选择项中被调用。.load() 方法从指定 URL 取得 HTML,之后使用返回的 HTML 来构成选择项元素。
// Using .load() to populate an element
$( "#newContent" ).load( "/foo.html" );
// Using .load() to populate an element based on a selector
$( "#newContent" ).load( "/foo.html #myDiv h1:first", function( html ) {
alert( "Content updated!" );
});
Ajax and Forms
Serialization
使用 .serialize() 和 .serializeArray() 来序列化表单的输入。
.serialize() 方法将表单数据序列化入查询字符串。为了使元素值可以被序列化,该元素必须有 name 属性。checkbox radio 类型的输入框,只有在被选中时,才会被包含入序列化中。
// Turning form data into a query string
$( "#myForm" ).serialize();
// Creates a query string like this:
// field_1=something&field2=somethingElse
然而简单原始的序列非常巨大,使用对象型的数组,代替查询字符串,会比较优秀。此时使用 .serializeArray() 方法,该方法产生对象型的数组,来代替字符创。
// Creating an array of objects containing form data
$( "#myForm" ).serializeArray();
// Creates a structure like this:
// [
// {
// name : "field_1",
// value : "something"
// },
// {
// name : "field_2",
// value : "somethingElse"
// }
// ]
Clident-side Validation
// Using validation to check for the presence of an input
$( "#form" ).submit(function( event ) {
// If .required's value's length is zero
if ( $( ".required" ).val().length === 0 ) {
// Usually show some kind of error message here
// Prevent the form from submitting
event.preventDefault();
} else {
// Run $.ajax() here
}
});
// Validate a phone number field
$( "#form" ).submit(function( event ) {
var inputtedPhoneNumber = $( "#phone" ).val();
// Match only numbers
var phoneNumberRegex = /^\d*$/;
// If the phone number doesn't match the regex
if ( !phoneNumberRegex.test( inputtedPhoneNumber ) ) {
// Usually show some kind of error message here
// Prevent the form from submitting
event.preventDefault();
} else {
// Run $.ajax() here
}
});
Prefiltering
预过滤器是一种在发送请求前改变 ajax 请求选项的方式。
// Using a proxy with a prefilter
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
if ( options.crossDomain ) {
options.url = "http://mydomain.net/proxy/" + encodeURIComponent( options.url );
options.crossDomain = false;
}
});
可以在回调函数之前传入参数,以指定那种数据类型应用预过滤器。
// Using the optional dataTypes argument
$.ajaxPrefilter( "json script", function( options, originalOptions, jqXHR ) {
// Do all of the prefiltering here, but only for
// requests that indicate a dataType of "JSON" or "script"
});
Working with JSONP
JSONP 本质上是一个双方同意的跨站脚本攻击。例如:Yahoo APIs
// Using YQL and JSONP
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql",
// The name of the callback parameter, as specified by the YQL service
jsonp: "callback",
// Tell jQuery we're expecting JSONP
dataType: "jsonp",
// Tell YQL what we want and that we want JSON
data: {
q: "select title,abstract,url from search.news where query=\"cat\"",
format: "json"
},
// Work with the response
success: function( response ) {
console.log( response ); // server response
}
});
Ajax Events
有时在在 Ajax 请求开始或停止时,会执行某些操作;例如:显示或者隐藏加载指示器。可以将 Ajax 事件绑定在元素上,而不是在每个 Ajax 请求中定义这些行为。完整文档:Ajax Events
// Setting up a loading indicator using Ajax Events
$( "#loading_indicator" )
.ajaxStart(function() {
$( this ).show();
})
.ajaxStop(function() {
$( this ).hide();
});