什么是Ajax?
Ajax的全程是Asynchronous Javascript and XML(即异步的JavaScript和XML,它并不是一种新的编程语言,而是几种原有技术的集合体)
ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
Ajax的优点:
- 通过异步模式,提升了用户体验
- 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
- Ajax引擎在客户端运行,承担了一部分本来由服务器承担的工作,从而减少了大用户量下的服务器负载。
Ajax的缺点:
- 不支持浏览器的后退按钮
- 安全问题 ajax暴露了与服务器交互的细节
- 对搜索引擎的支持比较弱
XMLHttpRequest对象
什么是XMLHttpRequest?
是一种支持异步请求的技术,它是ajax的核心。
XMLHttpRequest的作用:
- 可以向服务器提出请求并处理响应,而不阻塞用户。
- 可以在页面加载以后进行页面的局部更新。
要完整实现一个Ajax异步调用和局部刷新,通常需要以下几个步骤
- 创建XMLHttpRequest对象,也就是创建一个异步调用对象。(new XMLHttpRequest() )
- 创建一个新的http请求,并指定该http请求的方法,url(open)
- 设置响应http请求状态变化的函数(onreadystatechange)
- 发送http请求(send)
- 获取异步调用返回的数据
- 使用JavaScript和dom实现局部刷新
创建XMLHttpRequest对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax</title> </head> <body> <script> //封装通用的xhr对象,兼容各个浏览器 function createXHR() { //判断浏览器是否将XMLHttpRequest作用本地对象实现,针对ie7,firefox,oprea等 if ( typeof XMLHttpRequest != 'undefined' ) { return new XMLHttpRequest(); } else if ( typeof ActiveXObject != 'undefined' ) { //将所有可能出现ActiveXObject的版本放在一个数组内 var xhrArr = ['Microsoft.XMLHTTP', 'MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP.2.0', ]; //遍历创建XMLHttpRequest对象 var len = xhrArr.length,xhr; for ( var i = 0; i < len; i++ ) { try { //创建XMLHttpRequest对象 xhr = new ActiveXObject(xhrArr[i]); break; } catch (e) { } } return xhr; } else { throw new Error('No XHR object available'); } } </script>
//简单版 <script> function easyCreateXHR() { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); return xhr; } </script> </body> </html>
创建http请求
语法:open(method, url, async)
功能:创建http请求,规定请求的类型,url及是否异步处理请求。
参数说明:
- method:请求类型,GET或POST,默认get
- url:文件在服务器上的位置
- async:true(异步),false(同步),默认异步
注意事项:
open方法不会先服务器发送真正请求,它相当于初始化请求并准备发送只能向同一个域中使用相同协议和端口的url发送请求,否则会因为安全原因报错。
url:
url参数是open()方法中唯一一个必须要指定的参数,用来设置服务器上文件的地址,该文件可以是任何类型的文件,如.txt和.xml,或者服务器脚本文件,如.asp和.php(在传回响应之前,能够在服务器上执行任务)
GET和POST的区别:
与POST相比,GET更简单也更快,并且在大部分情况下都能用,然而,在以下情况中,必须使用POST请求:
- 无法使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST没有数据量限制)
- 发送包含未知字符的用户输入时,POST比GET更稳定也更可靠
同步和异步的区别:
同步:提交请求 ->等待服务器处理 -> 处理完毕返回 这个期间客户端浏览器不能干任何事
异步:请求通过事件触发 -> 服务器处理(这时浏览器仍然可以做其他事情) -> 处理完毕
设置响应http请求状态变化的函数:
在收到响应后,相应数据会填充到xhr对象的属性,由四个相关属性会被填充:
- responseText——从服务器进程返回数据的字符串形式
- responseXML——从服务器进程返回的DOM兼容的文档数据对象
- status——从服务器返回的数字代码,如404(未找到)和200(已就绪)
- statusText——伴随状态码的字符串信息
注意:这里常用的responseText返回的是字符串,要通过JSON.parse(xhr.responseText)将字符串转化为对象,才可以当成js对象使用;这里用eval()也可以转化,不过eval可以执行不符合JSON格式的代码,有可能会包含恶意代码,所以尽量少用。
发送请求
- 语法:send(string)
- 功能:将请求发送到服务器
- 参数说明:string仅用于post请求
- 注意事项:仅在POST请求时,可以传入参数,不需要则发送null,在调用send方法之后请求被发往服务器
在使用post请求时,需要设置http头:
- 语法:xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
以下是完整代码参考:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax</title> <link rel="stylesheet" href="style.css"> </head> <body> <div class="banner" id="banner"></div> <script> //封装通用的xhr对象,兼容各个浏览器 function createXHR() { //判断浏览器是否将XMLHttpRequest作用本地对象实现,针对ie7,firefox,oprea等 if ( typeof XMLHttpRequest != 'undefined' ) { return new XMLHttpRequest(); } else if ( typeof ActiveXObject != 'undefined' ) { //将所有可能出现ActiveXObject的版本放在一个数组内 var xhrArr = ['Microsoft.XMLHTTP', 'MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP.2.0', ]; //遍历创建XMLHttpRequest对象 var len = xhrArr.length,xhr; for ( var i = 0; i < len; i++ ) { try { //创建XMLHttpRequest对象 xhr = new ActiveXObject(xhrArr[i]); break; } catch (e) { } } return xhr; } else { throw new Error('No XHR object available'); } } </script> <script> function easyCreateXHR() { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); return xhr; } </script> <script> var xhr = createXHR(); var data = null; //设置响应XMLHttpRequest对象状态变化的函数,onreadystatechange在readystatechange属性发生改变时触发 xhr.onreadystatechange = function() { //异步调用成功,响应内容解析完成,可以在客户端调用 if ( xhr.readyState === 4 ) { if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 304 ) { //获得服务器返回的数据 // console.log(xhr.responseText); // console.log(xhr.responseXML); // console.log(xhr.statusText); // console.log(xhr.status); // console.log(xhr.readyState); // console.log(typeof xhr.responseText); // console.log(eval('(' + xhr.responseText + ')')); // console.log(JSON.parse(xhr.responseText)); data = JSON.parse(xhr.responseText); //渲染数据到页面中 renderDataToDom(); } } } //创建http请求,如果需要发送数据到后端,get请求可直接在url后添加参数。 xhr.open('get', './slider.json?user=zhangsan&user2=lisi', true); //发送请求,get请求 xhr.send(null); //如果用post请求,发送的数据需要写在send方法中。如下: // xhr.send({user: 'zhangsan', user2: 'lisi'}); // xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //渲染数据 function renderDataToDom() { var img = data.slider,i, len = img.length, str = ''; banner = document.getElementById('banner'); for (i = 0; i < len; i++) { str += '<a href="'+ img[i].linkUrl +'"><img src="'+ img[i].picUrl +'"></a>' } banner.innerHTML = str; } </script> </body> </html>
jQuery中的ajax使用
//jQuery的$.ajax() $.ajax({ url: "./slider.json", //请求地址 type: 'GET', //请求方式 async: true, //true异步,false同步 dataType: 'json', //数据格式 success: function(data) { //请求成功的回调 jQrenderDataToDom(data.slider); } });
跨域
同源策略
域名,协议,端口均相同才可以请求,只要有一项不满足,将无法请求,需要使用跨域实现。
如何解决跨域
- 跨域资源共享(CORS)
- 使用JSONP(常用)
- 修改document.domain
- 使用window.name
如何使用JSONP解决跨域
JSONP
是一种跨域的解决方案。
JSONP组成:
- 回调函数。是当响应到来时应该在页面中调用的函数。
- 数据。传入回调函数中的JSON数据。
JSONP的原理:
直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。
代码参考:
//封装JSONP function getJSONP(url, callback) { if (!url) { return; } //声明数组用来随机生成函数名 var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i', 'j'], r1 = Math.floor(Math.random() * 10), r2 = Math.floor(Math.random() * 10), r3 = Math.floor(Math.random() * 10), name = 'getJSONP' + arr[r1] + arr[r2] + arr[r3], cbname = 'getJSONP.' + name; //判断url地址中是否含有?号 if (url.indexOf('?') === -1) { url += '?jsonp=' + cbname; //这里//这里的'jsonp'这个字符串需要和后端约定 } else { url += '&jsonp=' + cbname; } console.log(url); //动态创建script标签 var script = document.createElement('script'); //定义被脚本执行的回调函数 getJSONP[name] = function(data) { try { callback && callback(data); } catch (e) { } finally { //最后删除该函数及script标签 delete getJSONP[name]; script.parentNode.removeChild(script); } } //定义script的src script.src = url; document.getElementsByTagName('head')[0].appendChild(script); } getJSONP('https://class.imooc.com/api/jsonp', function(data) { console.log(data); });