AJAX是什么?
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX还有一个最大的特点就是,当服务器响应时,不用刷新整个浏览器页面,而是可以局部刷新。这一特点给用户的感受是在不知不觉中完成请求和响应过程。可总结为
- 与服务器异步交互
- 浏览器页面局部刷新
那同步交互和异步交互的区别是什么?
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求
AJAX应用
最常见的是我们在百度输入东西时,百度只是局部刷新了一下即可,还有就是在网页注册登陆时,用到的也是这个原理,下面举个简单的登陆注册页面
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>用户名<input type="text" name="username" onblur="func1(this)" onfocus="func2(this)"> <span id="error"></span> </p> <p>密码<input type="password" name="password" onblur="func1(this)"><span id="pwd"></span></p> <input type="submit" value="submit"> <script> function func1(self) { var username = self.value; var xmlhttp = creteXMLHttpRequest(); xmlhttp.open("POST","/login/",true); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send("username="+username); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState == 4 && xmlhttp.status==200){ var data = xmlhttp.responseText; if (data=="1"){ document.getElementById("error").innerHTML="该用户已经存在"; document.getElementById("pwd").innerHTML="密码不符合朴准" } } }; } function func2(self) { document.getElementById("error").innerHTML="" } function creteXMLHttpRequest() { var xmlHttp; xmlHttp = new XMLHttpRequest(); return xmlHttp } </script> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def login(req): if req.method == "POST": username = req.POST.get("username") if username == "flash": return HttpResponse('1') return HttpResponse('0') return render(req, "login.html")
AJAX的优缺点
优点
- AJAX使用JavaScript技术向服务器发送异步请求。
- AJAX无需刷新整个页面。
- 因为服务器响应内容不再是整个页面,而是页面的局部,所以AJAX的性能高。
缺点
- AJAX并不适合所有场景,很得时候还是要使用同步交互。
- AJAX虽然提高了用户体验,但无形中向服务器发送的请求次数太多了,导致了服务器压力增大。
- 因为AJAX是在浏览器中使用JavaScript技术完成的,所以还要处理浏览器的兼容问题。
AJAX技术
主要可以概括为四部操作
- 创建核心对象;
- 使用核心对象打开与服务器的连接;
- 发送请求
- 注册监听,监听服务器响应
XMLHTTPRequest对象
所有现代浏览器均支持XMLHTTPRequest对象(IE5和IE6使用 ActiveXObject)。
XMLHTTPRequest用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
- open(请求方式, URL, 是否异步)
- send(请求体)
- onreadystatechange,指定监听函数,它会在xmlHttp对象的状态发生变化时被调用
内容信息
- readyState,当前xmlHttp对象的状态,其中4状态表示服务器响应结束
- status:服务器响应的状态码,只有服务器响应结束时才有这个东东,200表示响应成功;
- responseText:获取服务器的响应体
如果我们在创建对象时要考虑IE5和IE6的兼容性时,我们只需要,如果不需要,则不用写。
function createXMLHttpRequest() { var xmlHttp; // 适用于大多数浏览器,以及IE7和IE更高版本 try{ xmlHttp = new XMLHttpRequest(); } catch (e) { // 适用于IE6 try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { // 适用于IE5.5,以及IE更早版本 try{ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e){} } } return xmlHttp; }
AJAX-向服务器发送请求
我们可以使用XMLHttpRequest对象的open()方法和send()方法。
open(method,url,async):规定请求类型,URL以及是否异步处理请求
- menthod:请求的类型:GET或POST
- url:文件在服务器上的位置
- async: true(异步)或 flash(同步)。默认为true
send(string):将请求发送服务器请求
- string:仅用于POST
当在下面情况下时,要使用POST请求
- 无法使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST没有数据量限制)
- 发送包含未知字符用户输入时,POST比GET更稳定也更可靠
当我们使用POST请求时,需要注意的是在open和send之间添加如下信息即可
xmlhttp.open("POST","ajax_test.asp",true); xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xmlhttp.send("fname=Bill&lname=Gates");
服务器响应
XMLHttpRequest对象有一个onreadystatechange事件,它会在XMLHttpRequest对象的状态发生变化时被调用。下面介绍一下XMLHttpRequest对象的5种状态:
- 0:初始化未完成状态,只是创建了XMLHttpRequest对象,还未调用open()方法;
- 1:请求已开始,open()方法已调用,但还没调用send()方法;
- 2:请求发送完成状态,send()方法已调用;
- 3:开始读取服务器响应;
- 4:读取服务器响应结束。
onreadystatechange事件会在状态为1、2、3、4时引发。但通常我们只关心最后一种状态,即读取服务器响应结束时,客户端才会做出改变。我们可以通过XMLHttpRequest对象的readyState属性来得到XMLHttpRequest对象的状态。
xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4) { alert('hello'); } };
我们还需要考虑服务器响应的状态码是否为200等,可以用status获取状态妈如下
xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { alert(xmlHttp.responseText); } };
我们注意到了在获得来自服务器的响应时,可以使用responseText或responseXML属性来获取
- responseText:获取字符串的响应数据
- responseXML:获取XML形式的响应数据
jQuery实现AJAX
我们可以使用两个快捷方法去使用
$.get(url, [data], [callback], [type]) $.post(url, [data], [callback], [type])
下面以简单实例去看看如何显示。
def J_T(req): # print(req.GET) # 打印GET请求的数据 # print(req.POST) # 打印POST请求数据 #dic = {"name": "aa"} # return HttpResponse(json.dumps(dic)) return HttpResponse("OK")
<button id="b" onclick="func1()">点击</button>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> function func1() { test() } function test() { $.get('/J_T/'); $.post('/J_T/') } </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> function func1() { test() } function test() { $.get('/J_T/', function (data, callbacktype, jqXHR) { console.log(data); // OK console.log(callbacktype);//success console.log(jqXHR); //object }) } </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> function func1() { test() } function test() { $.get('/J_T/?a=12&b=4') $.get('/J_T/',{a:12,b:4}) $.post('/J_T/',{name:'aaa'}) } </script>
$.getScript()
$.getScript()使用 AJAX 请求,获取和运行 JavaScript:
function testGetScript() { // alert(testFun(3, 4)); $.getScript('test.js', function () { alert(add(1, 6)); }); } // test.js function add(a,b){ return a+b }
$.ajax的两种使用方式
function basicUsage() { //第一种 $.ajax('/test', { success: function () { alert('ok'); } }); //第二种 $.ajax({ url: '/test', success: function () { alert('okk'); } }); }
需要注意的事,success函数,在程序成功的时候会执行它,还有几种如下 success、error、statusCode、complete:
- success:程序执行成功时促发的函数
- error:程序执行失败时促发的函数
- complete:不管程序成不成功都会促发的函数
- statusCode:根据获取的状态码去对应的促发函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function callbacksUsage() {
$.ajax('/user/allusers', {
success: function (data) {
console.log(arguments);
console.log("aa")
},
error: function (jqXHR, textStatus, err) {
// jqXHR: jQuery增强的xhr
// textStatus: 请求完成状态
// err: 底层通过throw抛出的异常对象,类型与值与错误类型有关
console.log(arguments);
},
complete: function (jqXHR, textStatus) {
// jqXHR: jQuery增强的xhr
// textStatus: 请求完成状态 success | error
console.log('statusCode: %d, statusText: %s', jqXHR.status, jqXHR.statusText);
console.log('textStatus: %s', textStatus);
},
statusCode: {
'403': function (jqXHR, textStatus, err) {
console.log(arguments);
console.log('status code 403');
console.log("ahha403")
},
'400': function () {
console.log('status code 400');
console.log("hhhh400")
}
}
});
}
在向服务器请求时的数据可分为4种: data, processData, contentType, traditional
- data:当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。
- processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if 为false,那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString(),最后得到一个[object,Object]形式的结果。一般情况下不做处理。
- contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。用来指明当前请求的数据编码格式;urlencoded: ?a=1&b=2;如果想以其他方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串:
- traditional:一般是我们的data数据有数组时会用到
具体示例如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function testData() { $.ajax("/test",{////此时的data是一个json形式的对象 data:{ a:1, b:2 } }); //显示结果 ?a=1&b=2
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
$.ajax({
url:'/test/',
type:"POST",
data:{a:1,b:2},
processData:false, //默认为true,改成false后不需要转码直接发送,不常用
})
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
$.ajax("/test",{
data:JSON.stringify({
a:22,
b:33
}),
contentType:"application/json",
type:"POST",
});
//{a: 22, b: 33}
这里需要特别注意的是:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
$.ajax({
url:'/test/',
type:"POST",
data:{a:1,b:[3,4]}, //没加traditional之前{'b[]': ['3', '4'], 'a': ['1']}
traditional:true //加traditional之后 {'a': ['1'], 'b': ['3', '4']}
})
响应数据分为dataType、dataFilter:
dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;比如我们的服务器响应的content Type为json格式,这时ajax方法就会对响应的内容进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用data Type。比如服务器响应(Response Headers)的content Type是json格式(json对象),但是我们希望得到的是一个json字符串,那就可以把dataType:text,这样ajax方法就不会把返回的数据进行json格式的转换。
可用值:html|xml|json|text|script
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import csrf_exempt # Create your views here. import json def login(request): return render(request,'Ajax.html') def ajax_get(request): l=['aa','little aa'] #return HttpResponse(l) return HttpResponse(json.dumps(l)) //--------------------------------------------------- function testData() { $.ajax('ajax_get', { success: function (data) { console.log(typeof(data)); }, dataType:"json", } )} 注解:Response Headers的content Type为text/html,所以返回的是String;但如果我们想要一个json对象 设定dataType:"json"即可,相当于告诉ajax方法把服务器返回的数据转成json对象发送到前端.结果为objec
dataFilter:Function 给 Ajax返回的原始数据的进行预处理的函数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function testData() {
$.ajax('ajax_get', {
success: function (data) {
console.log(data);
},
dataType: 'json',
dataFilter: function(data, type) {
console.log(data);//["aa", "little aa"]
console.log(type);//json
//var tmp = JSON.parse(data);
return tmp.length;//2
}
});}
前置处理 beforeSend(XHR)
类型:Function 发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。这是一个 Ajax 事件。如果返回 false 可以取消本次 ajax 请求。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function testData() {
$.ajax('ajax_get', {
beforeSend: function (jqXHR, settings) {
console.log(arguments);
console.log('beforeSend');
jqXHR.setRequestHeader('test', 'haha');
jqXHR.testData = {a: 1, b: 2};
},
success: function (data) {
console.log(data);
},
complete: function (xhr) {
console.log(xhr);
console.log(xhr.testData);
},
})};
jsonp
类型:String
在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 "callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
jsonpCallback
类型:String
为 jsonp 请求指定一个回调函数名。这个值将用来取代 jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。
JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
JSON是用字符串来表示Javascript对象,例如可以在django中发送一个JSON格式的字符串给客户端Javascript,Javascript可以执行这个字符串,得到一个Javascript对象。json就是js对象的一种表现形式(字符串的形式)
JSON语法(使用双引号包含数据 "...")
- 数据在名称/值对中
- 数据由逗号分隔
- 花括号保存对象(对象需要使用大括号括起来)
- 方括号保存数组(数组使用中括号括起来)
JSON值
- 数字 (整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组 (在方括号中)
- 对象 (在花括号中)
- null
.parse()和.stringify()
- .parse()是从一个字符串中解析出json对象
- .stringify()是从一个对象中解析出字符串
var str = '{"name":"aa","age":"23"}' 结果: JSON.parse(str) str["name"]: aa str["age"]: 23 var a = {a:1,b:2} 结果: JSON.stringify(a) "{"a":1,"b":2}"
跨域请求
在执行跨域请求时,对方需给我们提供一个接口,否则无法完成
首先了解什么是同源策略?
览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。
jsonp的js实现
JSONP是JSON with Padding的略称。可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#---------------------------http://127.0.0.1:8001/login def login(request): print('hello ajax') return render(request,'index.html') #---------------------------返回用户的index.html <h1>发送JSONP数据</h1> <script> function fun1(arg){ alert("hello"+arg) } </script> <script src="http://127.0.0.1:8002/get_byjsonp/"></script> #-----------------------------http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): print('8002...') return HttpResponse('fun1("aaa")')
动态的去创建script标签
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> function addScriptTag(src){ var script = document.createElement('script'); //空标签 script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); //添加到body内 } function fun1(arg){ alert("hello"+arg) } window.onload=function(){ addScriptTag("http://127.0.0.1:8002/get_byjsonp/") } </script>
将自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } function fetch(arg){ alert("hello"+arg) } window.onload=function(){ addScriptTag("http://127.0.0.1:8002/get_byjsonp?callback=fetch") } </script> #--------------------------------http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): callback=req.GET.get('callback') print(callback) return HttpResponse('%s("aa")'%callback)
jQuery对JSONP的实现
jQuery使用时的方法为$.getJSON(url,[data],[callback])
<script type="text/javascript"> $.getJSON("http://127.0.0.1:8002/get_byjsonp?callback=?",function(arg){ alert("hello"+arg) }); </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script type="text/javascript" src="/static/jquery-2.2.3.js"></script> <script type="text/javascript"> $.ajax({ url:"http://127.0.0.1:8002/get_byjsonp", dataType:"jsonp", jsonp: 'callbacks', jsonpCallback:"fetch" }); function fetch(arg){ alert(arg); } </script> #--------------------------------- http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): callback=req.GET.get('callbacks') print(callback) return HttpResponse('%s("yuan")'%callback)
我们也可不用去自己定义
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script type="text/javascript" src="/static/jquery-2.2.3.js"></script> <script type="text/javascript"> $.ajax({ url:"http://127.0.0.1:8002/get_byjsonp", dataType:"jsonp", jsonp: 'callbacks', success:function(data){ alert(data) } }); </script> #-------------------------------------http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): callback=req.GET.get('callbacks') print(callback) #jQuery223015502220591490135_1477560648881 return HttpResponse("%s('aa')"%callback)
需要注意的是:jsonpCallback:"fetch";如果不加这个参数,则自动生成一个随机名字。
下面我们利用跨域请求去请求一个电视台的列表信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def index(req): return render(req, "index.html")
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button onclick="func1()">AJAX提交</button> <script src="/static/jquery-3.1.1.js"></script> <script> function func1() { $.ajax({ url:"http://www.jxntv.cn/data/jmd-jxtv2.html", type:"GET", dataType:"jsonp", }) } //这里lsit函数被后台定死了,所以在$.ajax内部也就不用写jsonp: 'callbacks'和jsonpCallback:"fetch"了 function list(e) { var obj=e['data']; $.each(obj,function () { //循环遍历,相当于for循环 console.log($(this)); var weekend=$(this)[0]["week"]; $("body").append("<p>"+weekend+"</p>"); var show_list=$(this)[0]["list"]; $.each(show_list,function () { var name=$(this)[0]["name"]; var link=$(this)[0]["link"]; $("body").append("<p><a href='" +link + "'>" + name+"</a></p>") }) }) } </script> </body> </html>