Ajax实用篇

在介绍ajax之前,博主想先介绍一些关于HTTP协议的知识.
例如百度的网址: http://www.baidu.com 我们可以看到,在整个域名地址的开头,有一个http协议,类似的还有https协议.

1.什么是Ajax?

Ajax全称:Asynchronous JavaScript+XML

它不是一个技术,实际上是几种技术的结合,合在一起就成了一个功能强大的新技术.

主要作用是在无刷新页面的情况下向服务器读取数据,可以应用在用户登入,在线聊天室等地方

2.编写一个Ajax

Ajax的核心实际是一个XMLHttpRequest对象,这个对象在目前的所有浏览器都支持,只是IE6 和 IE5的写法不一样而已。既然是一个对象的话,就存在它内置的属性和方法.

1.创建XMLHttpRequest对象

首先,我们要先创建XMLHttpRequest这么一个对象.
出于兼容性考虑,为了照顾IE5,6在这呢,我做了一个兼容性的处理

1
var  xhr = window.XMLHttpRequest ? XMLHttpRequest( ) : ActiveXObject("Microsoft.XMLHTTP");

XMLHttpRequest对象实际也是属于window的,所以出于严谨并避免不必要的麻烦,还是window.XMLHttpRequest比较好.
XMLHttpRequest()各大浏览器都支持
ActiveObject("Microsoft.XMLHTTP")是IE5.6的写法

2.连接到服务器

当xhr对象创建完毕之后,我们要使用一个open()的方法来连接到服务器
先来看下写法:

1
xhr.open('GET', 'msg.txt', true)

open()方法中有3个参数,我们分别来看下什么意思
第一个参数:
请求方法,一般是get或post
第二个参数:
请求是url
第三个参数:
是否为异步,默认true是异步,false是同步

3.监听请求状态

使用onreadystatechange方法,来监听请求状态.
请求状态xhr.readyState的值保存了xhr的状态
然而xhr一共有5种状态,分别是:

  • 0 未初始化。对象new出来了,但是还没有调用open方法
  • 1 启动。 已经调用open,但是还没有调用send方法
  • 2 发送。 已经send方法,但是还没有接收到相应
  • 3 接收。 已经开始接收数据,但是还没有完全接收。
  • 4 完成。 已经完全接收数据。
    我们主要监听的的第5种状态,也就是完全接收数据的状态.
    注:xhr.readyState==4只是表示接收数据完成,可以对数据进行处理了,此时还得再做一个判断看看服务器是否响应成功,也就是判断xhr.status是否为200,200表示成功,304虽然也表示成功,但是有缓存.
1
2
3
4
5
6
7
8
9
10
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200||xhr.status==304){
onSuccess(xhr.responseText);
}else{
if(typeof onFail=="function"){
onFail(xhr.status);
}
}
}

xhr.responseText指的是ajax向服务器请求之后返回的请求结果.

4.发送请求

使用xhr.send()方法来向服务器发送请求
send()方法内也可以传递参数,当使用get请求时,只要传递null就行了
(若是使用post请求方式的时候,()内可以传入一个数据参数data,后面会提到)

1
xhr.send(null)

通过以上四个步骤,我们已经会简单的使用ajax,但是在实际运用中,不可能要用到ajax的时候就再写一遍,那样很没有效率,所以我们可以将整段ajax代码封装到一个js代码中,在我们每次要用到ajax的时候,只需要调用这段js代码就可以了.
如下,我将以上的四个步骤封装到了一个myAjax对象中,这个对象中提供了俩个方法,一个是针对get调用,一个是针对post调用,俩个方法异曲同工,只不过在参数的使用上有一些的不同.具体代码如下:
文件名: myAjax.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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
var myAjax = {
/**
* 负责get请求
* @param url url地址
* @param onSuccess ajax请求成功时候的回调
* @param onFail ajax请求失败时候的回调
*/
get:function (url,onSuccess,onFail) {
if(!(typeof onSuccess=="function")) return;
var xhr = XMLHttpRequest ? new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('GET',url);
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200||xhr.status==304){
onSuccess(xhr.responseText);
}else{
if(typeof onFail=="function"){
onFail(xhr.status);
}

}
}
};
xhr.send(null);
},

/**
* 负责get请求
* @param url url地址
* @param data 请求的数据
* @param onSuccess ajax请求成功时候的回调
* @param onFail ajax请求失败时候的回调
*/
post:function (url,data,onSuccess,onFail) {
if(!(typeof onSuccess=="function")) return;
var xhr = XMLHttpRequest ? new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('POST',url);
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200||xhr.status==304){
onSuccess(xhr.responseText);
}else{
if(typeof onFail=="function"){
onFail(xhr.status);
}
}
}
};
//在发送请求之前必须添加这个请求头,表示表单数据进行url编码
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send(data);
}
}
};

这样当我们要用到ajax对象的时候,引用这段js代码就ok了.
例:
编写一个剪短的登入程序,当用户输入的用户名和密码和后台设置的一样,即显示登入成功.

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
31
32
33
34
35
36
1.编写一段php代码:
文件名: data.php

<?php
$name = $_POST["name"];
$age = $_POST["pwd"];
header('Content-type:text/html; charset="UTF-8"');
header("Access-Control-Allow-Origin:*");
if($name == "李四"&&$pwd=="123456"){
echo $name . "登入成功" ;
}else{
echo $name . "登入失败";
}
?>

2.HTML代码

<form action="data2.php" method="post" id="form1" enctype="application/x-www-form-urlencoded">
<input type="text" name="name">
<input type="text" name="pwd">
<input type="submit" value="登录">
</form>

3.引入ajax.js并编写js代码

<script type="text/javascript" src="myAjax.js"></script>
<script>
var form1 = document.querySelector('#form1');
form1.onsubmit=function (e) {
e.preventDefault();//阻止事件默认行为
var msg = "name=" + this.name.value+'&age="+this.age.value;
myAjax.post('data2.php',msg,function (result) {
console.log(result);
})
}
</script>

同源

通过博主上面的描述,相信大家对ajax都有了一定的了解,那么ajax这么牛能够使Web页面不用打断交互流程进行重新加载,就可以动态地更新,就没有什么限制吗?答案是有的,ajax访问网页的时候,ajax的地址,必须和当前页面同源,否则ajax就不能访问.
那么这里就要介绍一下同源.
在页面的地址栏里,我们经常可以看到我们输入的地址,都有一些相似之处,简单来说,一个网页的地址主要有这样几个组成部分:
协议://域名:端口号/资源路径?查询参数
https://www.baidu.com/s?ie=UTF-8&wd=王
那么只要俩个网址的 协议 域名 端口号 三个部分相同,这俩个网址就同源.
如:同源
http://www.baidu.com
http://www.baidu.com/abc/a.html
​ 不同源:
http://www.baidu.com
https://www.baidu.com/abc/a.html

不受同源策略的影响有:

1.img标签加载图片

2.script标签加载js文件

打破同源

现在主要是用俩种方式来打破同源,一直是利用jsonp,还有一种是服务器打破同源

1.jsonp

jsonp: json padding的简称,实际就是把json数据伪造为一个合理的js代码.
我们在正常读取json数据,得通过ajax来从服务器读取,但对于一些不同源的json数据,我们就无法正常读取,所以这时可以采用一个投机取巧的办法吧,就是把json数据伪造为一个合理的js代码,这样就能通过调用js代码来成功读取json数据,如看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
<script>
function foo(obj){
console.log(obj)
}
</script>
<script type= "text/script" src= "data.json"></script>


data.json:
foo({
name:'王先生'
})

将json数据用一个foo的函数封装起来,只要在要读取json数据的时候将json文件用script标签来引用,并通过foo函数调用就可以了.

2.服务器打破同源

就像前面说的,判断是否同源只要看协议域名端口号三个地方相同不相同,要是相同的话就是同源,我们的ajax就可以访问到.那么如果我们将服务器端口设置一下,也就是直接在我们的php文件中修改

1
2
3
在php文件的判断之前加上:
// *代表的就是所有域名都可以访问
header("Access-Control-Allow-Origin:*");

encodeURIComponent编码

其实每个汉字都有对应的URI编码,window提供了一个全局的方法encodeURIcomponent(),将中文转换为URI编码
一个中文由3个%号组成,如:

1
2
3
var name = encodeURIComponent('李四');
console.log(name);
=>%E6%9D%8E%E5%9B%9B

后文

Ajax实际就是通过get或者post方法在js中从php文件或者json文件读取到数据,然后在js中对这些数据进行操作.在实际的开发中,我们看到页面上的很多图片信息或者产品信息,都是通过Ajax读取数据然后添加到页面中.
另外,要是有小伙学过JQuery的话,会知道JQuery有它内置的Ajax,我们可以直接利用$.get(url,function(result){ })来读取数据.

评论