获取ajax对象
想要使用 ajax 的一系列功能,我们就必须先得到 ajax 对象
基于 W3C标准 浏览器:
var xhr = new XMLHttpRequest();
基于IE内核的浏览器:
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
<script>
var btu = document.getElementById('btu');
btu.onclick = function(){
//基于 W3C标准 浏览器
var xhr = new XMLHttpRequest();
alert(xhr);
//基于IE内核的浏览器, W3C标准浏览器中报错
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
alert(xhr);
}
</script>
浏览器标准不一样,得到的对象也不一样,我们也不知道客户使用什么样的浏览器,因此,我们需要解决兼容性问题;
修改上述代码并测试,具有兼容性:
var btu = document.getElementById('btu');
btu.onclick = function(){
try{
var xhr = new XMLHttpRequest()
}catch(e){
};
try{
var xhr = new ActiveXObject('Microsoft.XMLHTTP')
}catch(e){
};
alert(xhr);
}
再次对代码进行修改 兼容代码封装进函数调用
<script>
var btu = document.getElementById('btu');
btu.onclick = function(){
//封装进函数供其他程序调用
function cXHR(){
try{return new XMLHttpRequest()}catch(e){};
try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){};
}
alert(cXHR());
}
</script>
将函数写入单独的文件,共其他地方引入调用
创建createXHR.js
将函数复制到文件 createXHR.js 内并保存, 如图:
使用:
//文件引入
<script src="createXHR.js"></script>
<script>
var btu = document.getElementById('btu');
btu.onclick = function(){
//函数调用
alert(cXHR());
}
</script>
顺便封装一个方法:
使用id属性获取DOM对象,方便后面使用
function gid(id){
return document.getElementById(id);
}
ajax 对象的属性、方法 *
属性
readyState:Ajax状态码 *
1 表示对象已建立,但未初始化,只是 new 成功获取了对象,但是未调用open方法
2 表示对象已初始化,但未发送,调用了open方法,但是未调用send方法
3 已调用send方法进行请求
4 正在接收数据(接收到一部分),客户端已经接收到了一部分返回的数据
5 接收完成,客户端已经接收到了所有数据 *status:http响应状态码 200/300/400/500
statusText:http响应状态文本
responseText:如果服务器端返回字符串,使用responseText进行接收
responseXML:如果服务器端返回XML数据,使用responseXML进行接收
onreadystatechange:当 readyState 状态码发生改变时所触发的回调函数
方法
open(method,url,[aycs]):初始化Ajax对象 (打开)
method:http请求方式,get/post
url:请求的服务器地址
aycs:同步与异步setRequestHeader(header,value):设置请求头信息
header:请求头名称
value:请求头的值xhr.getAllResponseHeaders() 获取全部响应头信息
xhr.getResponseHeader(‘key’) 获取指定头信息
send([content]) :发送Ajax请求
1 content 如果是get请求时,此参数为null;
2 content 如果是post请求时,此参数就是要传递的数据注意: 所有相关的事件绑定必须在调用send()方法之前进行.
同步与异步
例如,小明去餐馆排队点餐,前台服务员将小明的菜单告诉厨师进行制作,此时小明后面排队的人就一直等着,
直到厨师制作完成,把饭菜送到小明手里后离开,后面的人才能继续点餐;这就是同步处理
但是,如果前台服务员将小明的菜单告诉厨师后,服务员发给小明一个好牌去旁边等待,后面的人继续点餐,
厨师将小明的饭菜做好后,随时呼唤小明就餐;这就是异步处理
服务器的不同做法,就代表着 Ajax 的同步或异步处理;
小明就是客户端;
厨师就是后台服务器;
图示:
PHP后台代码:
sleep(2);
$data = 't1';
echo $data;
前台代码:
<script src="createXHR.js"></script>
<script>
function t1(){
var xhr = cXHR();
xhr.onreadystatechange = function(){
if(this.readyState == 4){
alert(this.responseText);
}
}
//false同步
//true 异步
xhr.open('get','02.php', false);
xhr.send(null);
}
function t2(){
alert('t2');
}
t1();
t2();
</script>
判断用户名是否可用–案例
前台代码
<body>
<input type="text" value="" id="names">
<span id="tip"></span>
</body>
<script src="createXHR.js"></script>
<script>
var inp = gid('names');
inp.onblur = function(){
var xhr = cXHR();
xhr.onreadystatechange = function(){
if(xhr.readyState==4){
// alert(xhr.responseText);
if(xhr.responseText==1){
var h = '<font color="red">用户名已经被占用</font>';
gid('tip').innerHTML = h;
}else{
var h = '<font color="green">用户名可用</font>';
gid('tip').innerHTML = h;
}
}
}
xhr.open('get','03-1.php?names='+inp.value);
xhr.send();
}
</script>
后台PHP代码
$v = $_GET['names'];
//链接数据,查询是否存在用户名 //此步骤省略
if($v == 'admin'){
echo 1;
}else{
echo 0;
}
缓存问题
缓存的产生原因
在Ajax的get请求中,如果运行在IE内核的浏览器下,
其如果向同一个url发送多次请求时,就会产生所谓的缓存问题。
缓存问题最早设计初衷是为了加快应用程序的访问速度,
但是其会影响Ajax实时的获取服务器端的数据。
客户端解决缓存问题
产生缓存的问题就是 我们的客户端向同一个 url 发送了多次请求;
如果我们每次请求的url不同,那么,缓存问题就不会存在了;
我们可以在请求地址的后面加上一个无意义的参数,参数值使用随机数即可,
那么每次请求都会产生随机数,URL就会不同,缓存问题就被解决了;
Math.random():返回 0–1 之间的随机数,包括 0 但不包括 1;
修改代码如下:
var url = '03-1.php?names='+inp.value+'&_='+Math.random();
xhr.open('get',url);
但是,随机数虽然解决了问题,但是,我们不能保证每次生成的随机数都不一样;
也就是说,使用随机数存在一定的隐患;
new Date().getTime() : 获取当前时间的毫秒时间戳
修改代码如下:
var url = '03-1.php?names='+inp.value+'&_='+new Date().getTime();
xhr.open('get',url);
设置响应头禁用客户端缓存
服务器端在相应客户端请求时,可以设置相应头详细,如:
header(‘Content-type:text/html; charset=utf-8’) :告诉客户端浏览器,使用utf-8的编码格式解析页面信息。
在php代码中添加一下代码:
//告诉客户端浏览器不要缓存数据
header("Cache-Control: no-cache");
Ajax发送POST请求
post请求
复制第3章案例代码,将 get 请求修改为 post 请求;
//请求地址
var url = '03-1.php';
//open参数为post
xhr.open('post',url);
//设置请求头
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
//设置post请求参数值
xhr.send('names='+inp.value);
ajax中get请求与post请求的区别是:
1:传参方式
get请求在url尾部传递参数;
post 请求在send()方法中传递参数
2:请求头
post 请求需要生命请求头 xhr.setRequestHeader(‘Content-type’,’application/x-www-form-urlencoded’);
get 不需要设置;
3:参数值类型
get 传参值只能是数字、字符串
post 可以传递数字、字符串意外,还可以传递二进制数据;
Ajax 实现无刷新上传文件
普通文件上传,需要form表单,点击上传按钮后,页面会跳转:
HTML 代码:
<form action="05.php" method="post" enctype="multipart/form-data">
<input type="file" name="pic" > <br>
<input type="submit" value="上传" >
</form>
PHP后台移动文件代码:
//移动文件到新位置
move_uploaded_file($_FILES['pic']['tmp_name'],'./'.$_FILES['pic']['name']);
上传完成后,我们在浏览器中打开调试工具可以看到,如下图:
文件上传原理:
由此我们可以推断,文件上传的原理就是,浏览器客户端将文件载入并解析为二进制数据,
然后通过HTTP协议将数据发送到服务器端,文件上传就已经成功了;
但是对于服务器来说,接收到的文件会放到系统缓存中,
我们需要使用PHP的move_uploaded_file函数将文件移至我们设置好的目录下,并对缓存文件重新命名;
完成移动操作后,我们就可以在服务器端看见上传后的文件了;
想要使用Ajax完成文件上传,首先我们要学会,Ajax作为客户端如何将文件读入并解析为二进制数据;
HTML5为我们提供了 FormData 对象:
通过FormData对象可以组装一组用 XMLHttpRequest发送请求的键/值对。它可以更灵活方便的发送表单数据,因为可以独立于表单使用。
如果你把表单的编码类型设置为multipart/form-data,则通过FormData传输的数据格式和表单通过submit() 方法传输的数据格式相同;
<body>
<form id="fm" enctype="multipart/form-data" action="05.php" method="post">
<input type="file" name="pic" > <br>
<input type="submit" value="上传" id="su">
</form>
</body>
<script src="createXHR.js"></script>
<script>
var fm = gid('fm');
fm.onsubmit = function(){
var xhr = cXHR();
xhr.onreadystatechange = function(){
if(xhr.readyState==4){
if(xhr.responseText==1){
alert('上传成功');
}else{
alert('上传失败');
}
}
}
var url = '05.php';
xhr.open('post',url);
//FormData 会把表单的数据(包括文件流),整体打包
var fmdata = new FormData(this);
//发送整个FormData对象
xhr.send(fmdata);
//阻止提交跳转
return false;
}
</script>