四、Ajax示例

前面已经对ajax的源码结构和API有了一些介绍,下面就介绍一些ajax方法的应用;

前面已经介绍过了,Ajax中最最核心的方法就是$.ajax( url, options ),其它的方法都是在这个方法的基础上修改options参数实现的,下面来看一下ajax支持的options参数:

参数名类型说明
urlString发送请求的地址(默认值: 当前页地址)。
typeString请求方式 ("POST" 或 "GET"), 默认为 "GET"。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持
globalBoolean是否触发全局 AJAX 事件(默认: true)。设置为 false 将不会触发全局 AJAX 事件,如 ajaxStart 或 ajaxStop 。可用于控制不同的Ajax事件
processDataBoolean(默认: true) 默认情况下,发送的数据将被转换为对象(技术上讲并非字符串) 以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
asyncBoolean默认值: true。默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。 注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。
contentTypeString发送信息至服务器时内容编码类型(默认值: "application/x-www-form-urlencoded")
timeoutNumber设置请求超时时间(毫秒),此设置将覆盖全局设置
dataObject</br>String发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后。查看 processData 选项说明以禁止此自动转换。必须为 Key/Value 格式。如果为数组,jQuery 将自动为不同值对应同一个名称。如 {foo:["bar1", "bar2"]} 转换为 '&foo=bar1&foo=bar2'。
dataTypeString预期服务器返回的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息返回 responseXML 或 responseText,并作为回调函数参数传递,可用值:</br>"xml": 返回 XML 文档,可用 jQuery 处理;</br>"html": 返回纯文本 HTML 信息;包含 script 元素;</br>"script": 返回纯文本 JavaScript 代码。不会自动缓存结果。;</br>"json": 返回 JSON 数据 ;</br>"jsonp": JSONP 格式,使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。
usernameString用于响应 HTTP 访问认证请求的用户名
passwordString用于响应 HTTP 访问认证请求的密码
cacheBooleandataType 为 script 和 jsonp 时默认为 false;设置为 false 将不缓存此页面
traditionalBoolean如果你想要用传统的方式来序列化数据,那么就设置为 true
beforeSendFunction发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头;</br>beforeSend(XMLHttpRequest)
completeFunction请求完成后回调函数 (请求成功或失败时均调用)。参数: XMLHttpRequest 对象,成功信息字符串;</br>complete(XMLHttpRequest, textStatus)
errorFunction请求失败时将调用此方法。这个方法有三个参数:XMLHttpRequest 对象,错误信息,(可能)捕获的错误对象;</br> error(XMLHttpRequest, textStatus, errorThrown)
successFunction请求成功后回调函数。这个方法有两个参数:服务器返回数据,返回状态</br> success(data, textStatus)
xhrFunction需要返回一个 XMLHttpRequest 对象,默认在 IE 下是 ActiveXObject 而其他情况下是 XMLHttpRequest 。用于重写或者提供一个增强的 XMLHttpRequest 对象

.load( url, data, callback )

html:

<button>Load HTML one!</button>
<button>Load HTML two!</button>
<button>Load HTML three!</button>
<div id='ajax_content'></div>

js:

$('button').click(function(){
	var val = $(this).text();
	$('#ajax_content').load(
	    '/echo/html/',{
	        html: "<p>" + val + "</p>"
	    },function(text){
	    	console.log(text)
    });
});

上面的代码功能很简单,向/echo/html/发送一个ajax请求;请求数据为<p>元素包装的按钮的文本内容;回调函数callback仅仅接收一个参数text(即请求返回的文本内容),将其显示到控制台console上,该回调函数会在加载完响应之后执行。

当单击某个按钮过后,<div>元素里面的内容会是下面的某一个:

<p>Load HTML one!</p>
<p>Load HTML two!</p>
<p>Load HTML three!</p>

前面介绍过,.load()方法的功能是,将请求url响应直接插入到匹配元素中。可以直接将上面代码复制到JSFiddle.net上进行测试!

$.getJSON( url, data, callback )

在介绍$.getJSON()之前,首先说一下JSON(JavaScript Object Notation,JavaScript对象表示法),

JavaScript对象是由一些“key-value”对组成的,可以使用“{}”来定义,而数组则可以使用“[]”来定义,JSON就是将这两种语法组合起来,通过字面量的方式来表示数据,

{
	"key1": "value1",
	"key2': [
		"array_elem1",
		"array_elem2",
		"array_elem3"
	]
}

如是的JSON有很强的表达能力,能使用很少的空间大小来表示很多的数据,JSON规定了,所有的对象键及其键值都必须包含在双引号(““)中,而且函数不是有效的JSON值。

现在有如下一个a.json文件,其内容如下:

[
	{
    	"name"    : "Tom",
    	"birthday": "1991-01-23",
    	"hobbies": ["篮球","羽毛球","看电影"]
	},
	{
	    "name"    : "Jhon",
	    "birthday": "1987-09-06",
	    "hobbies": ["网球","看书","听音乐"]
	},
	{
	    "name"    : "James",
	    "birthday": "1989-10-23",
	    "hobbies": ["篮球","旅游","看书","玩游戏"]
	}
]

在页面加载时,将这些信息显示到页面中:

$.getJSON('a.json', function(data){
	var html = '';
	$.each(data, function( index, item ){
		html += '<div class="item">';
		html += '<h2>' + item.name + '</h2>';
		html += '<div class="birthday">' + item.birthday + '</div>';
		html += '<ul>';
		for(var i in item.hobbies){
			html += '<li>' + item.hobbies[i] + '</li>';
		}
		html += '</ul>';
		html += '</div>';
	});
	$('#content').html(html);
});

运行结果如下:

<div id="content">
	<div class="item">
	<h2>Tom</h2>
	<div class="birthday">1991-01-23</div>
	<ul>
		<li>篮球</li>
		<li>羽毛球</li>
		<li>看电影</li>
	</ul>
</div>
<div class="item">
	<h2>Jhon</h2>
	<div class="birthday">1987-09-06</div>
	<ul>
		<li>网球</li>
		<li>看书</li>
		<li>听音乐</li>
	</ul>
</div>
<div class="item">
	<h2>James</h2>
	<div class="birthday">1989-10-23</div>
	<ul>
		<li>篮球</li>
		<li>旅游</li>
		<li>看书</li>
		<li>玩游戏</li>
	</ul>
	</div>
</div>

$.getScript( url, callback )

a.js文件,其内容如下所示:

var data = [
	{
    	"name"    : "Tom",
    	"birthday": "1991-01-23",
    	"hobbies": ["篮球","羽毛球","看电影"]
	},
	{
	    "name"    : "Jhon",
	    "birthday": "1987-09-06",
	    "hobbies": ["网球","看书","听音乐"]
	},
	{
	    "name"    : "James",
	    "birthday": "1989-10-23",
	    "hobbies": ["篮球","旅游","看书","玩游戏"]
	}
];
var html = '';
$.each(data, function( index, item ){
	html += '<div class="item">';
	html += '<h2>' + item.name + '</h2>';
	html += '<div class="birthday">' + item.birthday + '</div>';
	html += '<ul>';
	for(var i in item.hobbies){
		html += '<li>' + item.hobbies[i] + '</li>';
	}
	html += '</ul>';
	html += '</div>';
});
$('#content').html(html);

页面的script代码:

$.getScript('/a.js',function(){
	console.log('ajax get script done!');
});

在上面上面的ajax请求script成功之后,会直接执行响应的a.js文件,结果跟$.getJSON的结果显示一样。

前面也介绍过$.getJSON$.geScript两个方法,调用最底层的ajax方法,然后为其指定了optioins,就成了这两个方法。

上面两个方法使用$.get$.ajax来实现的话,其请求操作如下:

// $.get
$.get( 'a.json', function(data){...}, 'json' );
$.get( 'b.js', underfined, function(){
	console.log('ajax get script done!');
}, 'script' );

// $.ajax
$.ajax({
	url: 'a.json',
	type: 'get',
	dataType: 'json',
	data: null,
	success: function(data){...}
});

$.ajax({
	url: 'b.js',
	type: 'get',
	dataType: 'script',
	data: null,
	success: function(){
		console.log('ajax get script done!');
	}
});

$.get()、$.post()

前面介绍$.get()$.post()的源码中,可以看出它们都是通过$.ajax()方法来实现的,唯一不同的是type(请求方式)不同,其它的都是一样的。

实际上get和post请求最大的区别是get请求把查询字符串放到url中,作为url的一部分;而post请求则不是,但是在jQuery的实现中,这种方式是没有体现出来的,都是直接通过传递一个data参数,在jQuery的底层实现中会将其转换成各自不同的实现,而我们是不需要去管它是怎么实现的。

jQuery中get和post的原型前面也介绍过,

$.get( url, data, callback )

$.post( url, data, callback )

可以看出其调用方式是一样的,只不过具体使用哪一种请求方式:(1)遵照服务器端代码的约定;(2)传输数据量–get方法对传输的数据量有更严格的限制。

序列化表单

向服务器发送数据常常会涉及到用户填写的表单,查询量较小的时候,可以手动的设置查询字符串,如:

$.get( 'c.html', {'name': $('input[name='name']').val()}, function(data){
	console.log(data);
});

但是当涉及到的表单数量较多的时候,手动的去序列化就不现实了,在这种情况下就可以使用jQuery提供的辅助方法.serialize(),该方法作用于一个jQuery对象,将匹配的DOM元素转换层能够随Ajax请求传递的查询字符串,例如前面的可以一般化为:

$('form').submit(function(event){
	event.preventDefault();
	var formValues = $(this).serialize();
	$.get( 'c.html', formValues, function(){
		$('#content').html(data);
	});
});

下面我们举例说明这个序列化的结果:

// html
<form action='#'>
	姓名:<input type='text' name='name'></br>
	年龄:<input type='text' name='age'></br>
	密码:<input type='password' name='password'></br>
	<input type='submit'/>
</form>

// js
$('form').submit(function(evnet){
	event.preventDefault();
	var va = $(this).serialize();
	$('#content').html(data);
});

当用户填写tom,20,tom123456,然后单击提交,就会看到控制台输出了:

name=tom&age=20&password=tom123456

.ajaxStart / .ajaxStop

前面我么说的一直都是在处理事件的响应,其实很多的时候,在调用ajax之前或调用过程中也需要处理一些事件,比如说:为了增强用户体验,在发送请求之间在页面显示一个Loading,在请求成功之后再将Loading去掉,再显示请求结果。

jQuery为我们提供了实现这样功能的函数,其中.ajaxStart()是在ajax尚未进行其它ajax时调用该函数,而.ajaxStop()是在最后一次请求结束之后再调用。jQuery提供的这些功能函数是全局性的,无论代码注册的位置在哪,只要满足了执行的条件,它都会运行。

例如实现上面说的Loading,先在html需要的位置插入一个显示加载中的显示元素,如<div id='loading'>Loading</div>,并将其设置为默认不显示,即添加一个样式style,display: none;,则html如下:

<div id='loading' style='display: none;'>
	Loading!
</div>

然后在js代码中需要的地方添加.ajaxStart即可,如:

$(document).ajaxStart(function(){
	$('#loading').show();
}).ajaxStop(function(){
	$('#loading').hide();
});

前面一篇介绍列出了所有jQuery提供的监听这些事件的方法,可以用来完成各种需要的操作,感兴趣的可以去尝试一下。

ajax中的Deferred对象

对于$.get/post.load等快捷的Ajax方法来说,并没有提供错误回调函数,只是提供了一个请求成功的回调函数,因此在错误发生的时候的处理函数需要通过其它方式来完成,比如说前面介绍过的Deferred延迟对象,它可以通过.done().fail().always()来为ajax请求添加相应的事件回调函数即可。

$.get( 'c.html', formValues, function(){
	$('#content').html(data);
}).fail(function(jqXHR){
	$('#content')
		.html('An error occurred:' + jqXHR.status)
		.append(jqXHR.responseText);
}).always(function(){
	console.log('ajax stop!');
});

更多的相关内容可以参考前面关于Deferred对象的讲解。

修改默认选项

使用$.ajaxSetup()方法可以修改调用Ajax方法是,每个选项的默认值,接受与$.ajax()相同的对象参数选项,如本文开头的表格所示,之后的所有Ajax请求都将使用传递给该函数的选项,除非用户显示的指定同名参数(将会覆盖默认设置)

// 修改默认选项
$.ajaxSetup({
	url: 'd.html',
	type: 'post',
	dataType: 'html'
});

// 再次调用ajax
$.ajax({
	type: 'get',
	success: function(data){
		$('#content').html(data);
	}
});

前面修改默认选项时,为ajax方法指定了默认的url(d.html)和dataType,后面调用时不需要在明确指定,如果再设置了与前面同名的选项,会覆盖前面的,就像这里的type,默认是post方式,而此处显示的指定了get方式,那么在本次的ajax请求会使用get方式去请求,如果下次没有显示指定请求方式,仍然会使用post方式去请求。

部分加载页面

前面介绍过的.load()方法,会将指定的文档全部添加到匹配元素中,而实际上可能只需要添加一部分。比如在加载一个html文档时,需要的只是这个html文档当中的class='part'的元素,不需要去遍历查找,直接传递url时附带一个jQuery选择符表达式即可,jQuery会帮我们完成必要的操作:

$('#content').load('c.html .part');

实际的操作语句就只有一句,非常的简洁,感兴趣的可以去试试看,你会发现与jQuery选择符表达式无关的信息都被剔除掉了,只将需要的信息加载到了匹配元素中。

</br>

===

未完待续。。。