概述
对于web应用程序:用户浏览器发送请求.服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML),渲染并显示浏览器上·
Ajax和Form表单提交数据的的好处有以下两种:
Form表单提交数据的时候,呈现在页面上是刷新整个页面·
Ajax提交数据的时候,只把有用的数据给提交过去,其余的不变·
1:传统的web应用
一个简单操作需要重新加载全局数据
2:AJAX
ajax,Asynchronous JavaScript and XML(异步的JavaScript和XML),一种创建交互式网页应用的网页开发技术方案·
· 异步的JavaScript:
使用[JavaScript语言]以及相关[浏览器提供类库]的功能向服务端发送请求,当服务端处理请求之后,[自动执行某个JavaSript的回调函数]·
PS:以上请求和响应的整个过程是(偷偷)进行的,页面上无任何感知·
·XML
XML是一种标记语言,是Ajax在和后台交互时传输数据的格式之一·
利用AJAX可以做:
1丶注册时,输入用户名自动检测用户是否已经存在·
2丶登录时,提示用户名密码错误·
3丶删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行业删除·
"伪"AJAX
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div> <p>请输入要加载的地址:<span id="currentTime"></span></p> <p> <input id="url" type="text" /> <input type="button" value="刷新" onclick="LoadPage();"> </p> </div> <div> <h3>加载页面位置:</h3> <iframe id="iframePosition" style=" 100%;height: 500px;"></iframe> </div> <script type="text/javascript"> //页面加载完成之后自动执行这个函数 window.onload= function(){ var myDate = new Date(); //创建一个时间对象 = 获取当前时间 document.getElementById('currentTime').innerText = myDate.getTime(); //把它的时间获取到 }; //LoadPage是由刷新触发的,一点刷新就执行LoadPage函数 function LoadPage(){ var targetUrl = document.getElementById('url').value; //输入什么值就获取都什么值 document.getElementById("iframePosition").src = targetUrl;
//输入什么URL“iframePosition”标签的src就等于什么 } </script> </body> </html>
原生AJAX
ajax主要就是使用[XmlHttpRequest]对象未完成请求的操作,该对象在主浏览器中均存在(除早期的IE),AJAX首次出现IE5.5存在(Active控件)·
1丶XmlHttpRequest对象介绍
xmlHttpRequest对象的主要方法:
1·void open(String metthod, String url, Boolen async) #用于创建请求 #参数: method:请求方式(字符串类型),如:POST,GET,DELETE... url:要请求的地址(字符串类型) async:是否异步(布尔类型) 2·viod send(String body) #用于发送请求 #参数 body:要发送的数据(字符串类型) 3·void setRequestHeader(String header,String value) #用于设置请求同 #参数: header:请求同的key(字符串类型) value:请求头的value(字符串的类型) 4· Strig getAllResponseHerders() #获取所有响应头 #返回值: 响应头数据(字符串类型) 5·String getResponseHeader(String header) #获取响应头中指定header的值 #参数: header:响应头的key(字符串类型) #返回值: 响应头中指定的header对应的值 6· void abort() #终止请求
XmlHttpRequest对象的主要属性 :
(数字类型)
1. Number readyState 状态值(整数) 详细: 0-未初始化,尚未调用open()方法; 1-启动,调用了open()方法,未调用send()方法; 2-发送,已经调用了send()方法,未接收到响应; 3-接收,已经接收到部分响应数据; 4-完成,已经接收到全部响应数据; 2. Function onreadystatechange 当readyState的值改变时自动触发执行其对应的函数(回调函数) 3. String responseText 服务器返回的数据(字符串类型) 4. XmlDocument responseXML 服务器返回的数据(Xml对象) 5. Number states 状态码(整数),如:200、404... 500(服务器错误) 404(没找到) 200系列的(都属正常) 6. String statesText 状态文本(字符串),如:OK、NotFound...
2丶跨浏览器支持
·XmlHttpRequest
IE7+,Firefox,Chrome,Opera,etc·
·ActiveXObject("Microsoft.XMLHTTP")
IE6,IE5
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>XMLHttpRequest - Ajax请求</h1> <input type="button" onclick="XmlGetRequest();" value="Get发送请求" /> <input type="button" onclick="XmlPostRequest();" value="Post发送请求" /> <script src="/statics/jquery-1.12.4.js"></script> <script type="text/javascript"> //创建xhr对象 function GetXHR(){ var xhr = null; //默认xhr = null if(XMLHttpRequest){ //如果(XMLHttpRequest)为真的话表示当前浏览器有这个东西
xhr = new XMLHttpRequest(); //通过 new创建一个对象 }else{ //否则的话 xhr = newActiveXobject("Miacosoft.XMLHttp"); //就用ActiveXobject这个插件用xhr去创建 } return xhr; //这样的话xhr就可以兼容这个浏览器了,兼容浏览器它给的返回值 } //就是一个可以发送那么一个ajax请求的的对象,拿到这个对象我们就可以发请求了 function XhrPostRequest(){ ver xhr = GetXHR(); //获取对象 //定义回调函数 xhr.obnreadystatechange = function(){ //执行成功之后的一个回调,这次请求执行成功了就会自动执行函数,
//只是定义了,完成之后才会执行,没完成就不会执行这个函数
if(xhr.readyState == 4){ //readyStat == 4 表示已经接收完毕
//已经接收到全部响应数据,执行以下操作 var data = xhr.responseText; //返回的文本内容 console.log(data); //打印 } }; //指定连接方式和地址----文件夹 xhr.open("POST","/test/",true); //打开这个链接,以post方式发送URL:/test/ //设置请求头 xhr.setRequestHeade("Content-Type","application/x-www-form-urlencong="utf-8"); //发送请求 xhr.send(); //发送 } } </script> </body> </html>
JQuery Ajax
jQuery其实就是一个Javascript的类库,其将复杂的功能做了上层封装,使得开发者可以在基础上写更少的代码实现更多的功能·
· jQuery不是生产者,而是大自然的搬运工·
· jQuery Ajax本质 XML HttpRequest 或 ActiveXobject
注:2.+版本不再支持IE9以下的浏览器
$.get({ url:"地址", data:"{"k1":"v1"}", //传输的数据 dataType:"json", // 这样写的话就会在内部执行字符串转成字典 success:function(xx){ //执行成功之后,就会自动执行个xx obj = JSON.parse(xx) //把字符串转换成字典 } }) $.getjson() //写着一句,相当于dataType在内部设置成json了 $.getscript() //写着一句,相当于dataType在内部设置成script了 $.post({ url:"地址", data:"{"k1":"v1"}", //传输的数据 success:function(xx){ //执行成功之后,就会自动执行个xx } }) $.ajax({ url:"地址", type:"post", //表示要发post请求 ..... }) //本质上get和post都会调用ajax方法
jQuery.get(...) 所有参数: url:待载入页面的url地址 data:待发送 key、value参数 success:载入成功时回调函数 dataType:返回内容格式,xml,json,script,text,html jQuery.post(....) 所有参数: url:带载入页面的url地址 data:待发送 key/value 参数 success:载入成功时回调函数 dataType:返回内容格式,xml,json,script,text,html jQyery.getScript(....) 所有参数: url;待载入页面的url地址 data:待发送key/value参数 success:载入成功时回调函数 jQuery.ajax(....) 部分参数: url:请求地址 type:请求方式,GET丶POST(1.9.0之后用method) headers:请求头 data:要发送的数据 contentType:即将发送信息至服务器的内容编码类型 (默认:"application/x-www-form-urlencoded;charset = utf-8") async:是否 异步 timeout:设置请求超时时间(毫秒) bempletet:完成之后执行回调函数(全局) su发送请求前执行回调函数(全局) coccess:成功之后执行的回调函数(全局) error:失败之后执行的回调函数(全局) accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型 dataType:将服务器端返回的数据转换成指定类型 “xml”:将服务器端返回的内容转换成xml格式 “text”:将服务器端返回的内容转换成普通文本格式 “html”:将服务器端返回的内容换换成普通文本格式,在插入DOM中时,如果包含Jvascript标签,则会尝试去执行 “script”:尝试将返回值当做javascript去执行,然后再将服务器端返回的内容转换成普通文本格式 “json”:将服务器端返回的内容转换成相应的Javascript对象 ‘jsonp’:JSONP格式 使用 JSONP 形式调用函数时,如"myurl?callback = ?" jQuery 将自动替换 ? 为正确的函数名, 以执行回调函数 如果不指定,jQuery 将自动根据HTTP包MIME信息返回相应类型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string converters: 转换器,将服务器端的内容根据指定的dataType转换类型,并传值给success回调函数 $.ajax({ accepts: { mycustomtype: 'application/x-some-custom-type' }, // Expect a `mycustomtype` back from server dataType: 'mycustomtype' // Instructions for how to deserialize a `mycustomtype` converters: { 'text mycustomtype': function(result) { // Do Stuff return newresult; } }, });
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="button" onclick="XmlSendRequest();" value='Ajax请求' /> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'GET', dataType: 'text', success: function(data, statusText, xmlHttpRequest){ console.log(data); } }) } </script> </body> </html>
跨域AJAX
由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档属性·
特别的:由于同源策略是 浏览器的限制,所有请求的发送和响应是可以进行,只不过浏览器不接受罢了·
浏览器同源策略并不是对所有的请求均制约:
·制约:XMLHttpRequese
·不叼:img,iframe,script灯具有src属性的标签
跨域,跨域名访问,如:http://www.c1.com 域名向 http://www.c2.com域名发送请求。
1丶JSONP实现跨域请求
JSONP(JSONP - JSON with Padding是JSON的一种 “使用模式”),利用 script标签src属性(浏览 器允许script标签跨域)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="button" onclick="Jsonp1();" value='提交'/> </p> <p> <input type="button" onclick="Jsonp2();" value='提交'/> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function Jsonp1(){ var tag = document.createElement('script'); tag.src = "http://c2.com:8000/test/"; document.head.appendChild(tag); document.head.removeChild(tag); } function Jsonp2(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'GET', dataType: 'JSONP', success: function(data, statusText, xmlHttpRequest){ console.log(data); } }) } </script> </body> </html>
2丶CORS
随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,既:跨域走远共享(CORS,Cross-Origin Resource Sharing),基本质是设置响应头,使得浏览器允许跨域请求·
*简单请求OR非简单请求
条件: 1丶请求方式:HEAD,GET,POST 2丶请求头信息: Accept Accept - Language Content - Language Last - Event - ID Content - Type 对应的值是以下三个中的任意一个 application/x- www - form - urlencoded multipart/form - data text/plain 注意:同时满足以上两个条件时,则 是简单请求,否则为复杂请求
*简单请求和非简单请求的区别?
1·简单请求:一次请求
2·非简单请求:两次请求,在发送数据之前会会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输·
*关于“预检”*
请求方式:OPTIONS
"预检":其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要的发送的消息·
如何“预检”:
如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Method
基于cors实现AJAX请求:
1丶支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = “域名”或“*”
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="submit" onclick="XmlSendRequest();" /> </p> <p> <input type="submit" onclick="JqSendRequest();" /> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function XmlSendRequest(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4) { var result = xhr.responseText; console.log(result); } }; xhr.open('GET', "http://c2.com:8000/test/", true); xhr.send(); } function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'GET', dataType: 'text', success: function(data, statusText, xmlHttpRequest){ console.log(data); } }) } </script> </body> </html>
import tornado.web import tornado.ioloop class MainHandler(tornado.web.RequestHandler): def get(self): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.write('{"status": true, "data": "seven"}')
2丶支持跨域,复杂请求
由于复杂请求时,首先会发送“预检”请求,如果‘预检’成功,则发送真实数据·
·‘预检’请求时,允许请求方则 需要服务器 设置响应头:Access-Control-Request-Method
·‘预检’请求时,允许请求头则需要服务器设置响应头;Access-Control-Request-Headers
·‘预检’缓存时间,服务器设置响应头:Access-Control-Max-Age
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="submit" onclick="XmlSendRequest();" /> </p> <p> <input type="submit" onclick="JqSendRequest();" /> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function XmlSendRequest(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4) { var result = xhr.responseText; console.log(result); } }; xhr.open('PUT', "http://c2.com:8000/test/", true); xhr.setRequestHeader('k1', 'v1'); xhr.send(); } function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'PUT', dataType: 'text', headers: {'k1': 'v1'}, success: function(data, statusText, xmlHttpRequest){ console.log(data); } }) } </script> </body> </html>
import tornado.web import tornado.ioloop class MainHandler(tornado.web.RequestHandler): def put(self): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.write('{"status": true, "data": "seven"}') def options(self, *args, **kwargs): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.set_header('Access-Control-Allow-Headers', "k1,k2") self.set_header('Access-Control-Allow-Methods', "PUT,DELETE") self.set_header('Access-Control-Max-Age', 10)
3丶跨域获取响应头
默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要服务器端设置Access-Contorl-Expose-Headers
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="submit" onclick="XmlSendRequest();" /> </p> <p> <input type="submit" onclick="JqSendRequest();" /> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function XmlSendRequest(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4) { var result = xhr.responseText; console.log(result); // 获取响应头 console.log(xhr.getAllResponseHeaders()); } }; xhr.open('PUT', "http://c2.com:8000/test/", true); xhr.setRequestHeader('k1', 'v1'); xhr.send(); } function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'PUT', dataType: 'text', headers: {'k1': 'v1'}, success: function(data, statusText, xmlHttpRequest){ console.log(data); // 获取响应头 console.log(xmlHttpRequest.getAllResponseHeaders()); } }) } </script> </body> </html>
class MainHandler(tornado.web.RequestHandler): def put(self): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.set_header('xxoo', "seven") self.set_header('bili', "daobidao") self.set_header('Access-Control-Expose-Headers', "xxoo,bili") self.write('{"status": true, "data": "seven"}') def options(self, *args, **kwargs): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.set_header('Access-Control-Allow-Headers', "k1,k2") self.set_header('Access-Control-Allow-Methods', "PUT,DELETE") self.set_header('Access-Control-Max-Age', 10)
4·跨域传输cookie
在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送·
如果想要发送:
·浏览器端:XMLHttpRequest的withCredentials为true
·服务器端:Access-Control-Allow-Credentials为true
·注意:服务器响应的Access-Control-Allow-Origin 不能是通配符 *
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="submit" onclick="XmlSendRequest();" /> </p> <p> <input type="submit" onclick="JqSendRequest();" /> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function XmlSendRequest(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4) { var result = xhr.responseText; console.log(result); } }; xhr.withCredentials = true; xhr.open('PUT', "http://c2.com:8000/test/", true); xhr.setRequestHeader('k1', 'v1'); xhr.send(); } function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'PUT', dataType: 'text', headers: {'k1': 'v1'}, xhrFields:{withCredentials: true}, success: function(data, statusText, xmlHttpRequest){ console.log(data); } }) } </script> </body> </html>
import tornado.web import tornado.inloop class MainHandler(tornado.web.RequestHandler): def put(self): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.set_header('Access-Control-Allow-Credentials', "true") self.set_header('xxoo', "seven") self.set_header('bili', "daobidao") self.set_header('Access-Control-Expose-Headers', "xxoo,bili") self.set_cookie('kkkkk', 'vvvvv'); self.write('{"status": true, "data": "seven"}') def options(self, *args, **kwargs): self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.set_header('Access-Control-Allow-Headers', "k1,k2") self.set_header('Access-Control-Allow-Methods', "PUT,DELETE") self.set_header('Access-Control-Max-Age', 10)