一、原生Ajax
在之前学习jQuery的时候,我们选择使用1.x版本,而没有选择使用2.x、3.x版本。
主要是因为1.x版本兼容以前比较老的浏览器,例如IE6 IE7等。
例如要使用Ajax,低版本的浏览器可能不支持xmlHttpRequest对象,而只支持另外一种IE使用的对象叫ActiveXObject。
在jQuery 1.x中,jquery.ajax会对这两种对象进行上层封装,也就是说两种都支持。
但在2.x和3.x中,jquery就放弃了低版本的浏览器,而只支持XHR对象。
1.使用原生Ajax(GET请求)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajaxtitle>
head>
<body>
<input type="text"/>
<input type="button" value="Ajax" onclick="send_ajax();"/>
<script>
// onclick事件,发送原生ajax请求
function send_ajax() {
// 创建一个xhr对象
var xhr = new XMLHttpRequest();
// 建立异步连接,第三个参数true表示异步
xhr.open('GET', '/ajaxproc/', true);
// 指定回调函数,每当readystate的值改变时,function就会被执行,当readystate为4时表示收到返回的数据
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
// 打印收到的数据
console.log(xhr.responseText);
// 打印收到的状态码,这个码是由视图函数HttpResponse(status=200)返回
console.log(xhr.status);
// 打印状态码对应的文本,HttpResponse(reason='文本')返回
console.log(xhr.statusText);
}
};
// 发送数据
xhr.send("username=root;password=123456");
}
script>
body>
html>
2.使用原生Ajax(POST请求)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajaxtitle>
head>
<body>
<input type="text"/>
<input type="button" value="Ajax" onclick="Ajax1();"/>
<script>
// onclick事件,发送原生ajax请求
function Ajax1() {
// 创建一个xhr对象
var xhr = new XMLHttpRequest();
// 建立异步连接,第三个参数true表示异步
xhr.open('POST', '/ajaxproc/', true);
// 指定回调函数,每当readystate的值改变时,function就会被执行,当readystate为4时表示收到返回的数据
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
// 打印收到的数据
console.log(xhr.responseText);
// 打印收到的状态码,这个码是由视图函数HttpResponse(status=200)返回
console.log(xhr.status);
// 打印状态码对应的文本,HttpResponse(reason='文本')返回
console.log(xhr.statusText);
}
};
// 要发post请求,必须设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
// 主要要设置csrf,这里省略,参考CSRF章节
// 发送数据
xhr.send("username=root;password=1234;");
}
script>
body>
html>
3.对应视图函数
def ajax(request): return render(request, 'ajax.html') def ajaxproc(request): import json def check_data(u, p): if u == 'leo' and p == '123456': return True else: return False if request.method == 'GET': if check_data(request.GET.get('username'), request.GET.get('password')): ret = {'code': 2000, 'data': "正确"} else: ret = {'code': 4000, 'data': "错误"} return HttpResponse(json.dumps(ret), status=200, reason="OK") if request.method == 'POST': if check_data(request.POST.get('username'), request.POST.get('password')): ret = {'code': 2000, 'data': "正确"} else: ret = {'code': 4000, 'data': "错误"} return HttpResponse(json.dumps(ret), status=200, reason="OK")
4.AJAX返回结果
二、XMLHttpResponse对象介绍
1.XMLHttpResponse对象的主要方法
a. void open(String method,String url,Boolen async)
用于创建请求
参数:
method: 请求方式(字符串类型),如:POST、GET、DELETE...
url: 要请求的地址(字符串类型)
async: 是否异步(布尔类型)
b. void send(String body)
用于发送请求
参数:
body: 要发送的数据(字符串类型)
c. void setRequestHeader(String header,String value)
用于设置请求头
参数:
header: 请求头的key(字符串类型)
vlaue: 请求头的value(字符串类型)
d. String getAllResponseHeaders()
获取所有响应头
返回值:
响应头数据(字符串类型)
e. String getResponseHeader(String header)
获取响应头中指定header的值
参数:
header: 响应头的key(字符串类型)
返回值:
响应头中指定的header对应的值
f. void abort()
终止请求
2.XMLHttpResponse对象的主要属性
a. Number readyState 状态值(整数) 详细: 0-未初始化,尚未调用open()方法; 1-启动,调用了open()方法,未调用send()方法; 2-发送,已经调用了send()方法,未接收到响应; 3-接收,已经接收到部分响应数据; 4-完成,已经接收到全部响应数据; b. Function onreadystatechange 当readyState的值改变时自动触发执行其对应的函数(回调函数) c. String responseText 服务器返回的数据(字符串类型) d. XmlDocument responseXML 服务器返回的数据(Xml对象) e. Number states 状态码(整数),如:200、404... f. String statesText 状态文本(字符串),如:OK、NotFound...
三、兼容性(跨浏览器支持)
主要针对旧版本IE浏览器和chrome浏览器之间的兼容。
XmlHttpRequest
IE7+, Firefox, Chrome, Opera, etc.
ActiveXObject("Microsoft.XMLHTTP")
IE6, IE5
如果我们想兼容低版本的IE浏览器,也就说当没有XMLHttpResponse的时候,使用ActiveXObject。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajaxtitle>
head>
<body>
<input type="text"/>
<input type="button" value="Ajax" onclick="Ajax1();"/>
<script>
// 获取XHR
function getXHR(){
var xhr=null;
if (XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
// onclick事件,发送原生ajax请求
function Ajax1() {
// 创建一个xhr对象
var xhr = getXHR();
// 建立异步连接,第三个参数true表示异步
xhr.open('POST', '/ajaxproc/', true);
// 指定回调函数,每当readystate的值改变时,function就会被执行,当readystate为4时表示收到返回的数据
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
// 打印收到的数据
console.log(xhr.responseText);
// 打印收到的状态码,这个码是由视图函数HttpResponse(status=200)返回
console.log(xhr.status);
// 打印状态码对应的文本,HttpResponse(reason='文本')返回
console.log(xhr.statusText);
}
};
// 要发post请求,必须设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
// 主要要设置csrf,这里省略,参考CSRF章节
// 发送数据
xhr.send("username=root;password=1234;");
}
script>
body>
html>
四、jQuery的Ajax
在前面我们已经使用过jQuery封装的Ajax。参照:[Python自学] day-20 (Django-ORM、Ajax) 第三节。
function Ajax1(){ $.ajax({ url: '/ajaxproc/', type: 'POST', data: {'username':'leo','password':'123456'}, success:function(data,str,xhr_obj) { console.log(data); console.log(typeof(str)); //打印success(string) console.log(xhr_obj); } }) }
假设我们使用jQuery.ajax,我们所定义的回调函数其实可以接收三个参数。第一个参数data就是服务器的返回值response。第二个参数返回的是一个字符串,成功返回'success'。
第三个参数很关键,他其实就是返回的$.ajax底层调用的XMLHttpResponse对象,也就是原生Ajax中我们new出来的xhr对象。
那就意味着,我们的全部数据都可以从xhr_obj这个参数中去获取:
function Ajax1(){ $.ajax({ url: '/ajaxproc/', type: 'POST', data: {'username':'leo','password':'123456'}, success:function(data,str,xhr_obj) { console.log(xhr_obj.responseText); console.log(xhr_obj.status); console.log(xhr_obj.statusText); } }) }
查看打印结果:
可以看到,这和原生Ajax一模一样。
五、伪Ajax
1.认识iframe标签
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Iframetitle>
head>
<body>
<iframe id="ifm" src="http://www.baidu.com" style="height: 400px;width: 800px;">iframe>
<input id='ifm_url' type="text"/>
<input type="button" value="发送" onclick="iframe_send();"/>
<script src="/static/jquery-1.12.4.js">script>
<script>
function iframe_send(){
var url = $("#ifm_url").val();
console.log(url);
$("#ifm").attr('src',url);
}
script>
body>
html>
页面效果:
可以看到,中间的百度页面就是iframe标签。因为
当我们在后面的text框中输入http://www.douyu.com,并点击发送,
此时
效果:
所以,iframe可以执行类似Ajax的异步操作,称之为伪Ajax操作。。
2.利用iframe标签提交表单
我们可以在表单中利用iframe为其提交数据:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Iframetitle>
head>
<body>
<form action="/ajaxproc/" method="post" target="ifm1">
<iframe name="ifm1">iframe>
<input type="text" name="username"/>
<input type="text" name="password"/>
<input type="text" name="email"/>
<input type="submit" name="Form提交"/>
form>
body>
html>
这样的话,这个表单提交的时候就会将数据交给iframe提交,返回值显示在iframe框中。
效果如下:
注意:
利用iframe时,视图函数需要加一个装饰器:
from django.views.decorators.clickjacking import xframe_options_exempt @xframe_options_exempt def ajaxproc(request): #......
如果不只用该装饰器,则会报错:
3.获取iframe的值
form利用iframe提交表单后,返回值是显示在iframe窗口中的,我们要如何来获取这些数据?
首先,我们看以下iframe中显示的值是什么:
可以看到,iframe中实际上嵌套了一个html页面。
当返回的数据返回到页面,并且往iframe中写时,iframe要触发一个onload事件。我们可以利用这个事件,来获取返回的数据。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Iframetitle>
head>
<body>
<form action="/ajaxproc/" method="post" target="ifm1">
<iframe id="ifm1" name="ifm1">iframe>
<input type="text" name="username"/>
<input type="text" name="password"/>
<input type="text" name="email"/>
<input type="submit" name="Form提交" onclick="bind_onload_event();"/>
form>
<script src="/static/jquery-1.12.4.js">script>
<script>
function bind_onload_event(){
//为iframe绑定onload事件函数,当数据回来时,则会触发
$("#ifm1").load(function(){
//在这里去获取数据
var text = $("#ifm1").contents().find('body').text();
console.log(text);
var obj = JSON.parse(text);
// 拿到obj后,就可以随意处理数据了
//todo..
})
}
script>
body>
html>
这样,我们就通过iframe发送异步请求,并成功获得了返回数据。在页面上,我们只需要隐藏iframe框就可以了。