前端必须掌握ajax,这是几乎所有前端招聘都会要求的一项。
但其实ajax也就是一种异步请求的技术,没有什么很深的东西,不过接触ajax很长一段时间了,早该整理下ajax的学习和使用:
PART1: 简单的例子
先通过一个简单地例子开始吧,通过请求一张图片来体验下(需要搭建服务器环境并开启服务器后才能正常使用ajax,以下的所有代码都是在服务器环境下测试的):
html:
<!DOCTYPE html>
<html lang="zh-cmn-Hans" id="html">
<head>
<title>ajax</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8">
<meta name="Description" content="SUperman">
</head>
<body>
<input id="getPic" type="submit" value="提交">
</body>
<script>
function ajax(){
var ajax;
if(XMLHttpRequest)
ajax = new XMLHttpRequest(); //IE7+,chrome,firefox
else
ajax = new ActiveXObject("Microsoft.XMLHTTP"); //超级老版本的IE
ajax.onreadystatechange=function(){
var state = ajax.readyState;
if(state==4&&ajax.status==200){
document.body.innerHTML=ajax.responseText; //responseText就是返回的文本信息
}
}
ajax.open("GET","response.php",true);
//三个参数相应表示:发送请求的方式(大小写均可,甚至大小写混用都行,但是可行不代表就应该这么用,还是用大写,培养良好的编程习惯),请求的url,布尔值true表示使用异步的方式
ajax.send(); //什么数据都不发送
}
$("getPic").onclick=function(){
ajax();
}
</script>
</html>
response.php,返回一个带有src的img标签:
<?php
echo"<img src='boy.png'></img>"; //返回dom文档片段
?>
于是点击按钮,就会通过异步请求的方式获取了一张图片并显示出来。此处省略截图。
PART2: 验证ajax异步请求方式
好问的同学此时会有疑惑,虽然open方法的第三个参数设置为true了,可是我怎么知道ajax请求真的就是异步的方式请求而不是同步的呢?
这个问题问得好,在下当时也是这么想的,那咱动手一试便知真伪。
修改下script代码,先看看异步情况是怎样的结果:
function ajax(){
var ajax;
if(XMLHttpRequest)
ajax = new XMLHttpRequest();
else
ajax = new ActiveXObject("Microsoft.XMLHTTP");
ajax.onreadystatechange=function(){
var state = ajax.readyState;
if(state==4&&ajax.status==200){
document.body.innerHTML=ajax.responseText;
console.log("ajax完成了,我可以出来了"); //请求发生完成
}
}
ajax.open("GET","response.php",true);
ajax.send();
console.log("hi,我是得到响应前的小可爱"); //同步编程
}
看下console的输出情况:
从这里可以看出使用的是异步方式,因为并没有等待ajax请求完成才执行下一步操作,console.log("hi,我是得到响应前的小可爱"); 先输出了。
改为同步编程的方式看看:
function ajax(){
var ajax;
if(XMLHttpRequest)
ajax = new XMLHttpRequest();
else
ajax = new ActiveXObject("Microsoft.XMLHTTP");
ajax.onreadystatechange=function(){
var state = ajax.readyState;
if(state==4&&ajax.status==200){
document.body.innerHTML=ajax.responseText;
console.log("ajax完成了,我可以出来了"); //请求发生完成
}
}
ajax.open("GET","response.php",false);
ajax.send();
console.log("hi,我是得到响应前的小可爱"); //同步编程
}
看下console的输出情况:
瞧,真的变成同步请求而不是异步请求了诶,先输出了请求完成的语句,这里ajax阻塞了主线程的执行,firefox还温馨提示不推荐使用同步ajax请求方式。
所以为了发挥ajax的真正作用,应该始终记得第三个参数是true,使用异步请求是ajax技术的初衷。
PART3: 获取JSON格式数据
由于一般使用JSON格式的数据来进行传输,所以修改下php,使得返回json数据:
<?php
echo '{"ajax":[{"name":"SUperman","number":1},
{"name":"苏苏","text":"byebye"}]}';
?>
ajax函数也相应的修改:
function ajax(){
var ajax;
if(XMLHttpRequest)
ajax = new XMLHttpRequest();
else
ajax = new ActiveXObject("Microsoft.XMLHTTP");
ajax.onreadystatechange=function(){
var state = ajax.readyState;
if(state==4&&ajax.status==200){
var response = JSON.parse(ajax.responseText); //转化为JSON对象,ie7-不支持JSON对象
var array = response['ajax'];
console.log(response);
if(array){
var c = document.createDocumentFragment();
for(i = 0, len = array.length; i < len; ++i){
var p = document.createElement("p");
for(j in array[i])
p.innerHTML += "<span>"+j+":</span>"+"<span>"+array[i][j]+" </span>";
c.appendChild(p);
}
document.body.appendChild(c)
}
}
}
ajax.open("GET","response.php",true);
ajax.send();
}
通过请求的response看下ajax得到的数据,从php代码也可以知道:
要方便的使用json数据要先用JSON.parse()方法(ie7-不支持)将数据转化为JSON对象,浏览器显示的是:
PART4: GET方式发送参数及对应的值到后台
现在,除了获取后台的数据,我还想传递参数给后台处理,可以将参数添加在open方法的url后面,如:
ajax.open("POST","response.php?name=某某某&&year=19",true);
表示将参数name和year以及对应的值传递给后台,
还是在浏览器开发工具中查看下, parameters就不再是空的了,它显示了要传递的参数:
修改下php的代码,使得返回传递的参数和值:
<?php
echo '{"ajax":[{"name":"'.$_REQUEST['name'].'","number":'.$_REQUEST['year'].'},
{"name":"苏苏","text":"byebye"}]}';
?>
结果如下:
看似一切正常。测试下浏览器,firefox和chrome是正常了,但是卧槽这放到ie就是歇菜的节奏啊:
这串"ijijij"哪来的,我的"某某某"呢,不科学!其实呢,这是字符编码的问题了,传递中文字符名-值对时应该先进行uri编码,
像这样:encodeURIComponent("某某某");将字符串作为uri组件单独编码。
修改之后,ie中打开就一切正常了,
从下图可以看出中文字符已经编码了:
当然啦,写程序就是为了不做重复的工作,可以用encodeURI() 函数将整串的包含请求参数的字符串作为 URI 进行编码。
像这样:ajax.open("GET",encodeURI("response.php?name=某某某&&year=19"),true);妥妥的解决问题。
当涉及传递参数时应先进行编码再发送请求,否则若有中文字符什么的很容易就给跪了。
PART5: POST方式如何发送数据呢,据说url不能太长诶
我现在对send()方法感到好奇了,通常各种书本上的例子调用send()都是传递空参数,那怎么利用起来呢,顾名思义,这个方法就是用来传递数据给后台的呀。
尝试修改send()方法:ajax.send("name=苏&&year=7"); 并且设置open方法改为POST的方式,然后悲剧的发现什么都没发生,
parameters显示(当然如果你不肯改为POST方式,那么你会发现请求的parameters是空的,有木有更悲剧-_-||):
卧槽,request payload什么鬼,同时发现http请求头部多了一点东西:
字符串长16是因为UTF-8 使用一至四个字节为每个字符编码。而中文汉字在utf-8中一般是占3个字节。所以这个长度是对的,但是却不能被后台获取到发送的数据。
赶紧上网找下资料,发现并没有对request payload有深入的讨论,表示有点伤心,但是提到了ajax使用post方式是想模拟表单post的方式来发送数据,也即form data的形式发送数据。
——————————————————————— 传说中的分割线 ——————————————————————————————
先来看看form表单如何发送请求。
对于这种get方式的form是没问题的:
<form action="response.php" method="GET">
<input type="text" name="name">
<input type="text" name="year">
<input type="submit">
</form>
parameters是querystring的形式:
而 http请求url是这样的:
改为post方式之后,http报头请求的url改变了,不携带参数了(或许这就是parameters是querystring的形式的原因):
而且content-type改变了:
parameters也相应的变成了Form data的形式,这就是我们要模拟的表单提交数据的方式!
另外当将参数添加到表单的action指向的url后面(必须是post方式,否则报错),而不是放在input中,parameters就变成和get方式一样了(再次相信这就是get方式下parameters是querystring的形式的原因)。
还需要指出的是,对于php响应表单的请求返回中文字符时不设置编码格式会跪掉的,给你显示乱码问你怕不怕。
ajax则不会,不过为了程序更加健壮,鲁棒性更强是吧,还是应该在response.php中设置传输的数据编码格式的:
header("Content-type: text/html; charset=utf-8");
嗯,完美,再也没有讨厌且恶心的乱码了。
——————————————————————— 结尾分割线 ——————————————————————————————
好了,回到post方式的ajax请求。为了模拟form data格式,要做的就是修改content-type了:
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
现在打开浏览器看看:
一切正常,parameters也是form data形式了。但是奇怪的是firefox中form data显示的name的值没有显示出来,还是将参数作为uri编码再发送吧:encodeURI("name=苏&&year=7"); 这下就能正常下显示了:
好像文章后面都要总结,可是也没什么好总结的了,就这样咯,写了好久,表示给跪。
-------------------------------转载注明出处^_^: http://www.cnblogs.com/suspiderweb/