ajax是异步JavaScript和xml的简称。
一. ajax补白
优势 | 不足(不一定是不足) |
不需要任何插件(但需要浏览器支持js) | XMLHttpRequest对象在不同浏览器下有差异 |
优秀的用户体验——不需要重复加载页面 | 破坏了浏览器前进后退的功能 |
提高了程序性能 | 搜索引擎不友好 |
把一部分负担有服务器端转移到客户端 | 开发难度大 |
1.XMLHttpRequest对象的属性和方法
从分析一个ajax.js开始
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
function ajax(url, fnSucc, fnFaild){ var oBtn=document.getElementById( 'btn1' ); oBtn.onclick= function (){ var oAjax= null ; if (window.XMLHttpRequest){ oAjax= new XMLHttpRequest(); } else { oAjax= new ActiveXObject( "Microsoft.XMLHTTP" ); }; oAjax.open( 'GET' , 'url' , true ); oAjax.send(); oAjax.onreadystatechange= function (){ if (oAjax.readyState==4){ if (oAjax.status==200){ fnSucc(oAjax.responseText); } else { if (fnFaild){ fnFaild(); } } } } } } |
ajax函数中三个参数分别是文本文件路径、接受成功时执行的函数,接收失败时执行的函数。
属性/方法/事件 |
描述 | 实例 | 备注 | |
1.readyState | readyState标识了当前对象的状态。 | |||
0 | 已创建 readyState但1未初始化 | |||
1 | 已调用open()方法,准备发送 | |||
2 | 已通过send()发送,但未收到响应 | |||
3 | 正在接收 | |||
4 | 完成响应 | |||
2.responseText | 接收到的文本内容 | 只有readyState值为4时,才收到完整的响应信息 | ||
3.responseXML | 描述被 XMLHttpRequest解析后的XML文档属性 | |||
4.status | http状态码 | oAjax.status==200表示响应正确 | readyState为3或4时才能访问。 | |
5.statusText | 状态码文本 | readyState为3或4时才能访问。 | ||
6.onreadystatechange(事件) | 每当readyState被改变时,都会触发onreadystatechange事件 | |||
7.open() | 有5个参数 | oAjax.open( 'GET' , 'url' , true ); |
||
method | 发送请求的方法 GET,POST,PUT,DELATE,HEAD |
要求大写 | ||
uri | 指定把请求发送到对应的URI | |||
acynic | 是否异步,默认为true | 当为true时send()方法才能被调用 | ||
username和password | 服务器验证访问状况 | |||
8.send() | 发送数据 | 没有open(),就没有send()。也就是说:readyState必须为1前提,才能调用。 | ||
9.abort() | 暂停接收或发送, XMLHttpRequest对象回归初始化状态。 | |||
10.setRequestHeader() | 请求头部信息 | readyState为1时才能调用 | ||
11.getResponseHeader() | 检索响应的头部值 | readyState为3或4是才能调用。否则得到null |
【例6.1】JavaScript实现ajax最简单的例子
1
2
|
< input id = "btn1" type = "button" value = "提交ajax请求" /> < div id = "resText" style = "width:300px;height:300px;border:1px solid #ccc;" ></ div > |
把ajax.js引入到文件中。编写如下ajax代码
1
2
3
4
5
6
7
8
9
10
|
window.onload= function (){ var oBtn=document.getElementById( 'btn1' ); var oTxt=document.getElementById( 'resText' ); oBtn.onclick= function (){ ajax( 'hello.txt' , function (str){ oTxt.innerHTML=str; }) } } |
由fnSucc(oAjax.responseText);可得知,获取的str是文件的文本。
二. jQuery和ajax
jQuery中的ajax方法
1.load()方法
载入远程 HTML 文件代码并插入至 DOM 中。默认使用 GET 方式 - 传递附加参数时自动转换为 POST 方式。参数如下:
1
|
load(url,[data,[callback]]); |
url是一个字符串,描述服务器端的地址;data(可选)是发送到服务器的key/value数据;callback(可选)是请求完成时的回调函数——无论成功还是失败。
【例6.2】构建一个html文档。点击按钮后加载到页面知指定区域。
(1)载入html文档。
继沿用例6.1的html框架,同时另构造一个hello.html文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<!DOCTYPE html> < html > < head > < meta charset = "UTF-8" /> </ head > < body > < 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 > </ body > </ html > |
1
2
3
4
5
|
$( function (){ $( '#btn1' ).click( function (){ $( '#resText' ).load( 'hello.html' ); }) }) |
大大减少了代码量
(2)筛选加载内容
hello.html的内容太冗余了。可以使用load(‘文档路径 选择器’),比如我只要para的内容可以
1
|
$( '#comment' ).load( 'hello.html .para' ) |
注意:原来html1的样式不会被代入resText中。
(3)传递
默认使用 GET 方式 - 传递附加参数时自动转换为 POST 方式。
(4)回调函数
加载完成后继续执行的函数。有三个参数
1
2
3
4
5
|
function (resposeText,textStatus,XMLRequest){ resposeText //请求返回的内容 textStatus //请求状态:success/error/notmodified/timout4种 XMLRequest //XMLRequest对象 } |
2. $.get()和$.post()方法
load只是获取静态的数据文件。
(1)$.get()
API给出的解释是:
通过远程 HTTP GET 请求载入信息。
这是一个可以替代复杂 $.ajax 简单的 GET 请求功能。请求成功时可调用回调函数。如果需要在出错时执行函数,请使用 $.ajax。
结构是
1
|
$.get(url,[data],[callback],[type]) |
url:待载入页面的URL地址
data:待发送 Key/value 参数。
callback:载入成功时才可以调用的回调函数。包括2个参数——
1
2
3
4
|
function (data,textStatus){ //data:返回的内容可以是XML,JSON,HTML文档(片段)等等 //textStatus:请求状态 } |
type:返回内容格式,xml, html, script, json, text, _default。
【例6.3】
编写html文档模拟一个发评论的布局
1
2
3
4
5
6
7
8
|
< form id = "form1" > < div class = "comment" >已有评论</ div > < div id = "resText" style = "width:300px;height:400px; border:1px solid #ccc;" ></ div > < p >评论</ p > < p >昵称< input type = "text" name = "username" id = "username" ></ p > < p >内容< textarea name = "content" id = "content" rows = "2" cols = "20" ></ textarea > < p >< input type = "button" id = "send" value = "提交" /></ p > </ form > |
用jQuery实现之。
有三种文件可以获取
a. 获取html片段
在index根目录下需要一个get1.php。用html的方式取值。
1
2
3
4
|
<?php header( "Content-Type:text/html; charset=utf-8" ); echo "<div class='comment'><h6>{$_REQUEST['username']}:</h6><p class='para'>{$_REQUEST['content']}</p></div>" ; ?> |
jq
1
2
3
4
5
6
7
8
9
10
|
$( function (){ $( '#send' ).click( function (){ $.get( 'get1.php' ,{ username:$( '#username' ).val(), content:$( '#content' ).val() }, function (data,status){ $( '#resText' ).html(data); }) }) }) |
b. 获取xml数据
在根目录下放一个get2.php。xml可以用类似html的方法取值
1
2
3
4
5
6
7
8
9
|
<?php header( "Content-Type:text/xml; charset=utf-8" ); echo "<?xml version='1.0' encoding='utf-8'?>" . "<comments>" . "<comment username='{$_REQUEST['username'] }' >" . "<content>{$_REQUEST['content']}</content>" . "</comment>" . "</comments>" ; ?> |
获取方法:把内容提取出来组合成一段html代码!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$( function (){ $( '#send' ).click( function (){ $.get( 'get2.php' ,{ username:$( '#username' ).val(), content:$( '#content' ).val() }, function (data,status){ var username=$(data).find( 'comment' ).attr( 'username' ); //获取get2.php的username var content=$(data).find( 'comment content' ).text(); // var txtHtml= '<div class="comment"><h6>' +username+ ':</h6><p class="para">' +content+ '</p></div>' ; $( '#resText' ).html(txtHtml); }) }) }) |
获取较为麻烦,xml文件也较大,但是应用范围较广。
c.json文件
json有相对较好的可读性。调取方法和原生JavaScript的数组差不多。比如
1
2
|
var arr={a:5,b:12,c:13}; alert(arr.b) //输出12 |
再如get3.php:
1
2
3
4
|
<?php header( "Content-Type:text/html; charset=utf-8" ); echo "{ \"username\" : \"{$_REQUEST['username']}\" , \"content\" : \"{$_REQUEST['content']}\"}" ?> |
jq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$( function (){ $( '#send' ).click( function (){ $.get( 'get3.php' ,{ username:$( '#username' ).val(), content:$( '#content' ).val() }, function (data,textStatus){ var username=data.username; //获取get3.php的username var content=data.content; //获取get3.php的content。 var txtHtml= '<div class="comment"><h6>' +username+ ':</h6><p class="para">' +content+ '</p></div>' ; $( '#resText' ).html(txtHtml); }, 'json' ); //$.get()的第四个参数设置为'json' }) }) |
但是,json对程序规范性要求非常严格。
以上三例的效果如下
(2)$.post()方法
$.post()方法结构和使用方法都和$.get()相同。区别在于
get方法——把数据放到网址来获取——安全性特别差但是便于分享。历史记录都可以看。——会缓存
如果用post方法,——把数据放到URL以外的地方来提交——适合用户注册——安全性一般。
url不可能太长,get方式的容量很低(不大于2k)。post的url是几乎无限的。——不缓存。
注意到php文档中都有这样一句话:
1
|
$_REQUEST [ 'xxx' ] |
其实,get和post都可以使用$_REQUEST['xxx']来获取对象。
回到load()方法的参数传递,默认使用 GET 方式 - 传递附加参数时自动转换为 POST 方式。那么可以直接这样写:
1
2
3
4
5
6
7
8
|
$( function (){ $( '#send' ).click( function (){ $.load( 'get3.php' ,{ username:$( '#username' ).val(), content:$( '#content' ).val() },fn(); }) }) |
默认就是post。
3. getScript()和getJson()方法。
(1)getScript()
情景:有时候,打开一个页面加载全部js是没必要的。比如qq空间。某些特效是到用时才触发。
对策:动态创建JavaScript标签。可以用DOM的方法创建,比如
1
|
$( '<script>............</script>' ) |
但getScript()方法更理想。把例6.3的js.js改为test.js,重新建一个js.js,让test.js默认不加载,当鼠标移到按钮上时加载。在js.js写:
1
2
3
4
5
|
$( function (){ $( '#send' ).mouseover( function (){ $.getScript( 'js/test.js' ); }) }) |
用起来和原来的没区别。但是这个test.js是之后加载的。在header区也看不到test.js的引入。
只是加载好像没什么意思,getScript()还提供了回调函数,比如说,
1
2
3
4
5
6
|
$( "#go" ).click( function (){ $( ".block" ).animate( { backgroundColor: 'pink' }, 1000 ) .animate( { backgroundColor: 'blue' }, 1000 ); }); }); |
加载对应插件,可以在回调函数中使用相对应的方法。
(2)getJson()
用于加载json文件,用法和getScript相同。
写一个test.json文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[ { "username" : "张三" , "content" : "沙发." }, { "username" : "李四" , "content" : "板凳." }, { "username" : "王五" , "content" : "地板." } ] |
要展现这个Jason的内容,回调函数应该怎么写呢?
思路:
$.each()通用例遍方法,可用于例遍对象和数组。
不同于例遍 jQuery 对象的 $().each() 方法,此方法可用于例遍任何对象。第一个参数是操作对象,第二个参数是个回调函数。
回调函数又拥有两个参数:第一个为对象的成员或数组的索引,第二个为对应变量或内容。如果需要退出 each 循环可使回调函数返回 false,其它返回值将被忽略。
举个栗子
1
2
3
|
$.each( [0,1,2], function (i, n){ alert( "Item #" + i + ": " + n ); }); |
输出
这样,数组[0,1,2]的对应成员就被显示出来了。
读取json可以用$.each(对象,回调函数(成员索引,对应索引内容))。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$( function (){ $( '#send' ).click( function () { $.getJSON( 'js/test.json' , function (data) { $( '#resText' ).empty(); var html = '' ; $.each( data , function (commentIndex, comment) { /*$.each表示遍历这个json,参数data是返回的数据本体,第二个参数是个回调函数 第二个回调函数function(commentIndex, comment)中,commentIndex表示数组的索引,第二个表示对应的内容*/ html += '<div class="comment"><h6>' + comment[ 'username' ] + ':</h6><p class="para">' + comment[ 'content' ] + '</p></div>' ; }) $( '#resText' ).html(html); }) }) }) |
点击之后可以在#resText中显示对应内容。
再进一步:通过jsonp形式的回调函数来加载其它网站的json数据。比如说从被墙图片网站中获取4张汽车类别的最新图片:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$( function (){ $( '#send' ).click( function () { $.getJSON( "http://api.flickr.com/services/feeds/photos_public.gne?tags=car&tagmode=any&format=json&jsoncallback=?" , function (data){ $.each(data.items, function ( i,item ){ $( "<img class='para'/> " ).attr( "src" , item.media.m ).appendTo( "#resText" ); if ( i == 3 ) { return false ; } }); } ); }) }) |
此例需要FQ。
4. $.ajax()方法
最底层的方法。一个参数是用来发送请求的url,另有一个请求参数——settings。settings包含了丰富的信息。以value/key的形式存在。
jQuery 底层 AJAX 实现。简单易用的高层实现见 $.get, $.post 等。$.ajax() 返回其创建的 XMLHttpRequest 对象。大多数情况下你无需直接操作该函数,除非你需要操作不常用的选项,以获得更多的灵活性。在此仅举一个实例展现之。参数详情见api文档。此处不过多深入。
获取一个text.js并加载
1
2
3
4
5
|
$.ajax({ type: "GET" , url: "test.js" , dataType: "script" }); |
5.序列化元素
(1)$.serialize()方法
回到提交评论的例子。通过
1
2
3
4
5
6
7
8
9
10
|
$( function (){ $( '#send' ).click( function (){ $.get( 'get1.php' ,{ username:$( '#username' ).val(), content:$( '#content' ).val() }, function (data,status){ $( '#resText' ).html(data); }) }) }) |
来获取用户名及评论内容。serialize()可以使序列表表格内容转化为字符串。
1
2
3
4
5
6
7
|
$( function (){ $( '#send' ).click( function (){ $.get( 'get1.php' ,$( '#form1' ).serialize(), function (data,textStatus){ $( '#resText' ).html(data); }) }) }) |
在此例中,data变成了字符串。
(2)$.serializeArray()方法
序列化表格元素 (类似 '.serialize()' 方法) 返回 JSON 数据结构数据。
'''注意''',此方法返回的是JSON对象而非JSON字符串。需要使用插件或者第三方库进行字符串化操作。
返回的JSON对象是由一个对象数组组成的,其中每个对象包含一个或两个名值对——name参数和value参数(如果value不为空的话)。
(3)$.param()方法
1
2
3
|
var params = { width:1680, height:1050 }; var str = jQuery.param(params); $( "#results" ).text(str); |
输出结果为
width=1680&height=1050
6.jQuery中的ajax全局事件。
一个栗子:读取远程数据时,加载可能会比较慢。这时需要一个过渡画面(loading),以全局事件函数作为判断,适时出现。
1
2
3
4
5
|
$( '#loading' ).ajaxStart( function (){ $( this ).show(); }).ajaxStop( function (){ $( this ).hide(); }) |
【大案例】没有了
原书中ajax聊天室案例在笔者电脑的服务器环境上无法正常运行,也许是配置出了问题。
本章看起来相当头疼,因为涉及了较多后端知识,书的编排基本遵照api文档。案例,怎么说呢,也是相当的旧。笔者在使用时旁敲侧击了很多不属于本书方法。这也是本系列文章的主要特征吧。
但是,有些旧案例还是以学习思想方法为主。所以能敲的还是要敲的。日后知识长进,还是要更新。
最后小结本章学到的东西,当然只是自己的理解
(1)ajax最重要是从数据库读取返回数据,弄明白原生参数很重要。
(2)jQuery基本的操作方法——
$.load()——载入、筛选、回调
$.get()、$.post()——操作不同类型的数据(xml,html,json)——get和post的区别——最底层的方法当然是$.ajax()——然而现实中用得不多。
选择性地加载数据——getScript;$.getJSON——加载json文件有自己的方法。
序列化元素——通过$.serialize()系列方法迅速转换。
全局事件——应用:加载需要时间,在等待时需要反馈用户适当的提示。