原生ajax相关内容,同步异步,cros跨域,jsonp跨域。
一、什么是AJAX
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。(局部刷新技术)
- AJAX 和请求数据有关。
- AJAX = 异步 JavaScript 和 XML(XML也是一种树形结构文档,写法和html写法一致,写的标签是自定义的标签)。
- 是一种用于创建快速动态网页的技术。
- AJAX 通过在后台与服务器进行少量数据交换,返回到前端,使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
- 传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
二、五步法书写原生ajax
1、创建XMLHttpRequest对象( 考虑 ie5 ie6的兼容)
2、使用open
方法建立连接
参数:
(1)method——请求的方式(get 、post)
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
但是在以下情况中,请使用 POST 请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
(2)url——文件在服务器上的地址
该文件可以是任何类型的文件,比如 .txt 和 .xml,或者服务器脚本文件,比如 .asp 和 .php (在传回响应之前,能够在服务器上执行任务)。
注意:
如果请求方式为get,并且URL里边只写文件地址的话,那么可能得到的是缓存的结果,为了避免浏览器缓存,可以向URL 添加一个唯一的id,如:
xmlhttp.open("GET","/try/ajax/demo_get.php?t=" + Math.random(),true);
post方式就不需要考虑这个问题。
(3)async——ajax 请求是异步还是同步( 默认是异步,true 异步 false 同步)
异步就是:在等待服务器响应时执行其他脚本,当响应就绪后对响应进行处理。
XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true。
原生js不能使用同步,因为ajax对象在主线程。
当使用 async=true 时,需要规定在响应处于 onreadystatechange 事件中的就绪状态时执行的函数;
当使用 async=false 时,不要编写 onreadystatechange 函数 - 把代码放到 send() 语句后面即可。
一般不推荐使用 async=false,但是对于一些小型的请求,也是可以的。
需要注意的是,JavaScript 会等到服务器响应就绪才继续执行。如果服务器繁忙或缓慢,应用程序会挂起或停止。
(4)用户名(指的是服务器的用户名和密码)
(5)密码
3、使用send
方法发送请求
如果需要像 HTML 表单那样传递数据:
请求方式为get,传递的数据直接写在 url 路径之后,如:
xmlhttp.open("GET","http://www.maodou.com/getdata?id=10086&pwd=12345",true);
send();
请求方式为post,需要使用 setRequestHeader()
来添加 HTTP 头,然后将传递的数据写在 send 方法里面,如:
xmlhttp.open("POST","/try/ajax/demo_post2.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
send("fname=Henry&lname=Ford");
注意:setRequestHeader()
要写在open之后,send之前。
4、ajax响应事件
当请求被发送到服务器时,我们需要执行一些基于响应的任务。
当 readyState 等于 4 且状态为 200 时,表示响应已就绪:
readyState 属性存有 XMLHttpRequest 的状态信息,从 0 到 4 发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
每当 readyState 改变时,就会触发 onreadystatechange
事件。
(onreadystatechange 事件被触发 4 次(0 - 4), 分别是: 0-1、1-2、2-3、3-4,对应着 readyState 的每个变化。)
status
200-服务器响应成功
404-页面丢失
500-服务器报错
5、页面更新
如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。
response
获得object形式的响应数据。
responseText
:获得string形式的响应数据。
responseXML
:获得 XML 形式的响应数据。
完整代码如下:
<script>
//1.创建ajax对象
var xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else {
//考虑ie5 ie6 兼容性
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.建立连接
xmlHttp.open("get", "", true);
//3.发送请求
xmlHttp.send();
//4.响应事件
xmlHttp.onreadystatechange = function () {
//readyState==4 读取完成
//status==200 服务器响应成功 404 页面丢失 500 服务器报错
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
//5.获取服务器响应数据
//下面两个都是服务器响应数据
xmlHttp.response; //object
xmlHttp.responseText; //string
//拿到数据 操作dom 更新界面
}
}
</script>
三、原生ajax 的封装
<script>
//ajax封装 根据请求方式 和 是否传给服务器递数据data进行判断
function ajax(method, url, data, callback) {
var xmlHttp;
//做兼容处理
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
if (method == "get") {
if (data) {
url += "?";
url += data;
}
xmlHttp.open(method, url, true);
xmlHttp.send();
}
else {
xmlHttp.open(method, url, true);
//设置响应头
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
if (data) {
xmlHttp.send(data);
}
else {
xmlHttp.send();
}
}
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
callback(xmlHttp.response);
}
}
}
//使用的时候直接调方法
//这里使用了回调函数 使得后端返回的数据xmlHttp.response可以在外边使用
ajax("get", "./data/stu.json", null, function (res) {
console.log(res);
})
</script>
注意:
如果需要发送数据,data 必须为以下格式:
var data = "id=10086&name=张三&sex=男";
四、ajax 跨域问题
1、ajax请求出现跨域错误的原因
ajax出现请求跨域错误问题,主要原因就是因为同源政策规定,AJAX请求只能发给同源的网址,否则就报错。即:
- 协议相同
- 域名相同
- 端口相同
如果非“同源”,共有三种行为受到限制:
- Cookie、LocalStorage 和 IndexDB 无法读取。
- DOM 无法获得。
- AJAX 请求不能发送。
虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下边是 AJAX 请求不能发送 时的解决方案。其它两种情况的解决方案参考:
浏览器同源政策及其规避方法——阮一峰
2、ajax跨域的表现
3、ajax请求出现跨域错误的解决方案
(1)CROS方式
直接去后端设置 header(头信息) Access-Control-Allow-Origin: *
允许所有域名访问。
Access-Control-Allow-Origin
这个字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*
,表示接受任意域名的请求。
更多关于CROS的问题,可以参考:
跨域资源共享CROS详解——阮一峰
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
相比JSONP只能发GET
请求,CORS允许任何类型的请求。
(2)JSONP方式
JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
缺点:只能发送GET
请求。
它的基本思想是,网页通过添加一个<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
- JSONP 跨域是通过前端
src
访问后端接口,传递参数以及回调函数(因为在前端,src
属性可以直接连接远程的api
(程序应用集,也叫接口));- 后端接收回调函数,返回回调函数的执行(携带实参)到前端——把数据通过实参的形式传递给前端;
- 前端的函数执行,获取服务器响应。
写法:
<script>
function getData(res) {
console.log(res);
}
</script>
<script src="http://jia.maodou.com:8000/addinfo?id=10086&name=张三&callback=getData"></script>
注意:先定义函数,再调用API接口。
3、document.domain + iframe跨域
使用该方案的前提:
这两个域名必须属于同一个一级域名。而且所用的协议,端口都要一致,否则无法利用document.domain
进行跨域。
举例:
news.baidu.com
里的一个网页(news.html
)引入了map.baidu.com
里的一个网页(map.html
)
这时news.html
里是不能操作map.html
里面的内容的。
因为document.domain
不一样,一个是news.baidu.com
,另一个是map.baidu.com
。
这时我们就可以通过Javascript,对两个域名进行降级处理,即将两个页面的domain改成一样的,
需要在a.html
里与b.html
里都加入:
document.domain = “baidu.com”;
代码如下:
news.baidu.com下的news.html页面:
<script>
document.domain = 'baidu.com';
var ifr = document.createElement('iframe');
ifr.src = 'map.baidu.com/map.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
// 这里可以操作map.baidu.com下的map.html页面
var oUl = doc.getElementById('ul1');
alert(oUl.innerHTML);
ifr.onload = null;
};
</script>
map.baidu.com下的map.html页面:
<ul id="ul1">我是map.baidu.com中的ul</ul>
<script>
document.domain = 'baidu.com';
</script>