AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。
其实简单点说,AJAX 就是 JS 中的一个对象而已,就是 XMLHttpRequest对象
同步与异步
AJAX 是一种异步加载的技术多使用在表单提交、(滚动)加载更多、输入提示等方面
先来了解下同步请求是什么,比如提交一个表单,流程可以是:
点击提交后,客户端向服务器发起请求,服务器进行处理,然后返回结果给客户机,然后客户端刷新页面显示结果;
在客户端发起请求后,是一直处于等待服务器响应的状态的,没法做别的事,这是同步的一种体现
还是上面的例子,如果是异步请求,那就是在你输入某一个信息后,就会携带某个信息立即向服务器发起请求,服务器返回结果,从而调用 js/css 来显示给用户输入是否正确(比如用户名是否重复)
在这个过程用户完全可以继续填其他的内容,也不会刷新页面,这就是异步的一种体现
向服务器发送请求
前面我们说过,AJAX 的核心就是 XMLHttpRequest 对象,所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
1 | var xmlhttp=new XMLHttpRequest(); |
注意 send 方法,如果是 GET 请求,因为参数都在 URL 中,所以不需要填(填了也没用),如果是 POST 请求,那么就必须把参数传入 send 方法了
服务器响应
对于对象来说,响应就很简单了,ajax 支持三种类型的数据:
- String
- XML
- JSON
其中 String 和 JSON 的 MIME 类型都是 text/plain
都是使用 responseText 来接收;而 XML 类型的数据使用 responseXML 来接收,MIME 是 text/xml
在服务端设置的时候需要注意。
1 | // 获得字符串形式的响应数据。 |
我们可以通过监听 readyState 属性来实现:
readyState 属性的变化代表服务器响应的变化
0:请求未初始化,open还没有调用
1:服务器连接已建立,open已经调用了
2:请求已接收,也就是接收到头信息了
3:请求处理中,也就是接收到了响应主体
4:请求已完成,且响应已就绪,也就是响应完成了
1 | var request = new XMLHttpRequest(); |
需要注意的是,不同的浏览器对这几种状态码的支持是不一样的,也就是说有的浏览器没有 0,有的没有 1;但是肯定都支持 4;
并且只有在状态码发生变化后才会触发这个函数,所以说如果状态码一直是 4 也不会触发这个函数
解析XML
如果是 XML 的数据,那么解析的例子:
1 | function callback2() { |
其中,for 循环为了避免每次都判断 length 属性浪费性能,所以单独提出来,如果对顺序没要求,可以直接采用倒序遍历的方式,就没有这个问题了。
为了避免字符串拼接的效率问题,使用数组来代替字符串的拼接,主要是 push 方法增加,最后使用 join("")
转成字符串,如果直接使用 toString 方法那会输出 abc,def,aa,xx
,所以使用 join 来处理。
解析JSON
JSON 类型的数据应该是最常见的,同时解析也非常的简单,因为 JSON 的语法和 JS 的对象定义基本完全一致的。
一般原生 JS 解析 JSON 可以使用两种方式:
JSON.parse(str)
eval('(' + str + ')')
后面的遍历就简单了,完全按照 JS 中的对象处理来。
用jQuery实现
jQuery 已经帮我们封装好了,使用起来也非常的方便
1 | // 发送数据 |
data :是一个对象,连同请求发送到服务器的数据
dataType:预期服务器返回的数据类型,如果不指定将根据 HTTP 包中的 MIME 信息智能判断,一般我们都用 JSON 格式
如果是 Json 类型的数据还可以使用 JavaScript 原生的 JSON.parse
方法进行转换成对象,jQuery 中使用 ajax 请求的方式除了上面的栗子有下面几种:
- jQuery.load( url, [data], [callback] )
默认使用 GET 方式来传递的,如果 [data] 参数有传递数据进去,就会自动转换为 POST 方式的。 - jQuery.get( url, [data], [callback] )
相似的还有一个$.getJSON()
方法,只是被限定为 JSON 类型 - jQuery.post( url, [data], [callback], [type] )
- jQuery.getScript( url, [callback] )
通过 GET 方式请求载入并执行一个 JavaScript 文件
$.ajax()
是所有 ajax 方法中最底层的方法,所有其他方法都是基于 $.ajax()
方法的封装,jQuery 真的是博大精深啊
callback 函数可以有三个参数,第一个就是服务器返回是数据了(对象形式,和服务器端的实体对象对应),第二个是状态码,第三个是 ajax 对象。
跨域
在浏览器的规则中 JavaScript 是不被允许访问其他域下的内容的,只有在子域名和主域名都相同的情况下才不算跨域,端口号也必须相同
http 与 https 之间也算是跨域
解决这个问题,一般的几种方式为:
使用代理
属于后端技术,比如写个 PHP 页面专门用来转发请求,后端访问是没有问题的
JSONP (只支持GET请求)
出于安全考虑,浏览器都有同源策略。即相同 domain(域) 的页面运行在一个沙箱(sandbox)中,与其他 domain 的沙箱隔离,不能跨越 domain 直接访问其他 domain 下的资源。
但HTML中有几个标签可以忽略同源限制去请求其他 domain 下的资源,比如<img>
和<script>
等。比如当浏览器解析到<script>
标签,就会发起一个get请求,请求的 URL 即为 scr 所指定的 url。这就相当于跨域访问了一个资源。
JSONP 就是这样的原理,我们可以利用 Src 来跨域得到我们想要的数据,但这这样就会变成下面的样子
1 | <script> |
但这样的数据解析很麻烦,所以 JSONP 做了下处理,返回的结果是:my_callback({['some string 1', 'some data', 'whatever data']});
可以看到,这里的返回结果是直接执行了一个函数 my_callback(...)
, 实参就是我们需要的数据;那么只要在代码里实现 my_callback 函数,就可以做任何想做的事了
当然也可以使用 jQuery 来做,type 选择 jsonp,然后增加一个属性 jsonp,值可以任意,其实就是上面的那个函数名
然后在跨域的服务端要获取到这个名字,可以看出是在 url 传递了一个参数,所以也就只支持GET请求了,比如:
1 | $.ajax({ |
后端代码以 PHP 为例
1 | $jsonp = $_GET["callback"]; |
简单说就是在 script 标签里我们请求 :<script src=‘http://b.com?callback=fun’ />
,为了方便后端返回把函数名当做参数传回去了,后端拿到这个参数就相当于拿到了回调函数的名称,然后拼一个函数把数据当做参数传入就行了(fun('datadatadata')
),这样前台就能直接调用了,方法的定义在前台
并且后端处理更灵活,如果发现没带 callback 参数那就返回正常的 JSON 数据,如果带了就返回 JSONP 的格式,一个接口适应了两种情况
XHR2
HTML5 提供的 XMLHttpRequest Level2 已经实现了跨域访问以及其他的一些新功能
在服务器端加入下面两句
那个域可以访问,* 表示所有
header(‘Access-Control-Allow-Origin:*‘);
支持什么方法
header(‘Access-Control-Allow-Methods:POST,GET’);
其他补充
异步请求使用一个 XMLHttpRequest 对象就足够了,发起的异步请求都会交给它来处理,它内部必然有个类似数组结构的变量来存,然后依次请求服务器(将原始请求进行包装,然后以 http 协议发送),当响应完成后(通过流的形式)再由 XMLHttpRequest 通知调用方(返回给调用方)进行处理;
Ajax 其实就是起到了一个中转的作用
利用 js 将 select 元素的 options 的长度设为 1,会只保留第一项其他的全部清空,比如: selectElement.options.length = 1
ajax 技术还经常用在验证码的时候,判断输入的个数以及按键弹起事件(onkeyup)通过后,通过 ajax 从后台获取输入的是否正确,及时给予用户提示
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~