Ajax
一. Ajax
#AJAX = 异步 JavaScript和XML(标准通用标记语言的子集) #AJAX 是一种用于创建快速动态网页的技术。 #通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 #传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面 #使用Javascript向服务器提出请求并处理响应而不阻塞用户!核心对象XMLHTTPRequest。通过这个对象,您的JavaScript 可在不重载页面的情况与Web服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效果 #目的:AJAX不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。 #Ajax主要就是使用 【XmlHttpRequest】对象来完成请求的操作,该对象在主流浏览器中均存在(除早起的IE),Ajax首次出现IE5.5中存在(ActiveX控件)。
a. XmlHttpRequest对象的主要方法:
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() 终止请求
b. XmlHttpRequest对象的主要属性:
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...
c. 原生Ajax 和 jQueery Ajax
1. XMLHttpRequest 2. jQuery Ajax(“jQuery Ajax本质 XMLHttpRequest 或 ActiveXObject”)
1. 原生Post/Get 和 jQuery Ajax 向后台发送请求
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^jQuery_add/', views.jQuery_add), url(r'^Ajax_add/', views.Ajax_add), ]
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def index(request): return render(request,"index.html") def jQuery_add(request): a1 = int(request.POST.get("a1")) a2 = int(request.POST.get("a2")) return HttpResponse(a1+a2) def Ajax_add(request): if request.method == "GET": a1 = int(request.GET.get("a1")) a2 = int(request.GET.get("a2")) print("Ajax_add....") return HttpResponse(a1+a2) else: a1 = int(request.POST.get("a1")) a2 = int(request.POST.get("a2")) return HttpResponse(a1+a2)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="text" id="a1"> + <input type="text" id="a2"> = <input type="text" id="a3"> <input type="submit" value="jQuery提交" onclick="jQuery_add()"> <input type="submit" value="Ajax_get_提交" onclick="Ajax_get_add()"> <input type="submit" value="Ajax_post_提交" onclick="Ajax_post_add()"> <script src="/static/jquery-3.2.1.js"></script> <script> function jQuery_add() { $.ajax({ url:"/jQuery_add/", type:"POST", data:{"a1":$("#a1").val(),"a2":$("#a2").val()}, success:function (arg) { $("#a3").val(arg); } }) } function Ajax_get_add() { var xhr = new XMLHttpRequest(); d1 = $("#a1").val(); d2 = $("#a2").val(); xhr.onreadystatechange = function () { if(xhr.readyState ==4){ $("#a3").val(xhr.responseText) } }; xhr.open("GET","/Ajax_add/?a1=" + d1 +"&a2=" + d2 +""); xhr.send(); } function Ajax_post_add() { var xhr = new XMLHttpRequest(); d1 = $("#a1").val(); d2 = $("#a2").val(); xhr.onreadystatechange = function () { if(xhr.readyState ==4){ $("#a3").val(xhr.responseText) } }; xhr.open("POST","/Ajax_add/"); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send("a1=" + d1 +"&a2=" + d2 +""); } </script> </body> </html>
d. 伪Ajax (非XMLHttpRequest)
1. iframe标签
#iframe标签: 具有不刷新页面就可以发送HTTP请求的功能 #由于HTML标签的iframe标签具有局部加载内容的特性,所以可以使用其来伪造Ajax请求
iframe演示
urlpatterns = [ url(r'^autohome/', views.autohome), ]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div> <input type="text" id="txt1" /> <input type="button" value="查看" onclick="changeScr();"/> </div> <iframe id="ifr" style="width: 1000px;height: 2000px;" src="http://www.autohome.com.cn"></iframe> <script> function changeScr(){ var inp = document.getElementById('txt1').value; document.getElementById('ifr').src = inp; } </script> </body> </html>
def autohome(request): return render(request,'autohome.html')
2. 通过iframe form 实现伪Ajax向后端发送请求
urlpatterns = [ url(r'^fake_ajax/', views.fake_ajax), ]
def fake_ajax(request): if request.method == "GET": return render(request,"fake_ajax.html") else: print(request.POST) return HttpResponse("...")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="f1" action="/fake_ajax/" method="POST" target="ifr"> <iframe id="ifr" name="ifr" style="display: none"></iframe> <input type="text" name="user"> <a onclick="submitForm()">提交</a> </form> <script> function submitForm() { document.getElementById("f1").submit(); document.getElementById("ifr").onload = loadIframe; } function loadIframe() { var content = document.getElementById("ifr").contentWindow.document.body.innerText alert(content) } </script> </body> </html>
二. 基于Ajax上传文件
a. 通过创建 FormData()对象,发送字符串
urlpatterns = [ url(r'^upload/', views.upload), ]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>原生Ajax上传文件</h3> {# <input type="file" id="i1">#} <a onclick="upload()">上传</a> <script src="/static/jquery-3.2.1.js"></script> <script> function upload() { var formdata = new FormData(); //创建一个对象 formdata.append("k1","v1"); //字符串 var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if(xhr.readyState ==4){ alert(xhr.responseText) } }; xhr.open("POST","/upload/"); {# xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");#} //发送字符串的时候不需要加上面 xhr.send(formdata); //发送字符串, } </script> </body> </html>
def upload(request): if request.method == "GET": return render(request,"upload.html") else: print(request.POST,request.FILES) return HttpResponse("...")
b. 原生Ajax上传文件
urlpatterns = [ url(r'^upload/', views.upload), ]
import os def upload(request): if request.method == "GET": return render(request,"upload.html") else: print(request.POST,request.FILES) file_obj = request.FILES.get("file") file_path = os.path.join("static",file_obj.name) with open(file_path,"wb") as f: for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse(file_path)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>原生Ajax上传文件</h3> <input type="file" id="i1"> <a onclick="upload()">上传</a> <div id="container1"> </div> <script src="/static/jquery-3.2.1.js"></script> <script> function upload() { var formdata = new FormData(); //创建一个对象 formdata.append("k1","v1"); formdata.append("file",document.getElementById("i1").files[0]); var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if(xhr.readyState ==4){ var file_path = xhr.responseText; var tag = document.createElement("img"); tag.src = "/" + file_path; document.getElementById("container1").appendChild(tag); } }; xhr.open("POST","/upload/"); xhr.send(formdata); } </script> </body> </html>
c. jQuery 上传文件
urlpatterns = [ url(r'^upload/', views.upload), ]
import os def upload(request): if request.method == "GET": return render(request,"upload.html") else: print(request.POST,request.FILES) file_obj = request.FILES.get("file") file_path = os.path.join("static",file_obj.name) with open(file_path,"wb") as f: for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse(file_path) return HttpResponse("...")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>原生jQery上传文件</h3> <input type="file" id="i2"> <a onclick="upload2()">上传</a> <div id="container2"> </div> <script src="/static/jquery-3.2.1.js"></script> <script> function upload2() { var formdata = new FormData(); //创建一个对象 formdata.append("k1","v1"); formdata.append("file",$("#i2")[0].files[0]); $.ajax({ url: "/upload/", type: "POST", data:formdata, contentType:false, processData:false, //这两个参数是formdata jquery不做数据的处理 ,以原生的formdata向后端传数据 success:function (arg) { var tag = document.createElement("img"); tag.src = "/" + arg; $("#container2").append(tag); } }) } </script> </body> </html>
d.伪造
urlpatterns = [ url(r'^upload/', views.upload), ]
import os def upload(request): if request.method == "GET": return render(request,"upload.html") else: print(request.POST,request.FILES) file_obj = request.FILES.get("file") file_path = os.path.join("static",file_obj.name) with open(file_path,"wb") as f: for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse(file_path) return HttpResponse("...")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>伪 Ajax上传文件</h3> //enctype="multipart/form-data" #form表单传文件加 <form id="f1" action="/upload/" method="POST" target="ifr" enctype="multipart/form-data"> <iframe id="ifr" name="ifr" style="display: none"></iframe> <input type="file" name="file"> <a onclick="upload3()">上传</a> </form> <div id="container3"></div> <script src="/static/jquery-3.2.1.js"></script> <script> function upload3() { document.getElementById("f1").submit(); document.getElementById("ifr").onload = loadIframe; } function loadIframe() { var content = document.getElementById("ifr").contentWindow.document.body.innerText; var tag = document.createElement("img"); tag.src = "/" + content; $("#container3").append(tag); } </script> </body> </html>
三. Jsonp
json 是一种数据格式 之前 Ajax 提交请求时候没有写IP和端口 是自己给自己发送 称作同源 现在 Ajax 提交请求时候向其它IP或端口发送请求 对方可以接收请求并返回数据 但客户端浏览器拦截不能接收跨域的数据 同源策略在限制 同源策略是指域名 协议 端口相同 同源策略是浏览器加的 Ajax出现跨域问题 a img没有出现问题 Ajax请求 实现跨域强求数据 - jsonp - cors
- 同源策略 浏览器做的限制,访问自己网站可以,访问其它网站,浏览器会限制 - 限制 Ajax - 不限制 script - jsonp是一种方式,目的是解决跨域问题 - 其它 - 只能发get请求 - 约定 - 开发需求 向其它网站发送Http请求 - 浏览器直接发送请求[考虑同源] - 浏览器-->服务端-->发送请求 - 浏览器直接发送请求[考虑同源] - 要求: 1. 客户端 - URL?callback=xxx - function xxx(arg) 2. 服务端 -获取 funcname = request.GET.get(callback) -返回 funcname(...)
a. 自创建 script 从www.s4.com跨域向www.s5.com发送数据,接受数据
1. www.s4.com
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^jsonp/', views.jsonp), ]
def jsonp(request): return render(request,"jsonp.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers()"> <ul id="user_list"></ul> <script> function getUsers() { var tag = document.createElement("script"); tag.src = "http://www.s5.com:9000/user/?callback=bbb"; document.head.appendChild(tag); } function bbb(arg) { console.log(arg); for (var i=0 ;i<arg.length;i++){ var tag = document.createElement("li"); tag.innerText = arg[i]; document.getElementById("user_list").appendChild(tag); } } </script> </body> </html>
2. www.s5.com
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^user', views.user), ]
from django.shortcuts import render,HttpResponse # Create your views here. import json def user(request): v = request.GET.get("callback") print("请求来了") user_list = ["alex","egon","root"] user_list_str = json.dumps(user_list) temp = "%s(%s)" % (v,user_list_str) print(temp) return HttpResponse(temp)
b. jQuery跨域发送数据
1. www.s4.com
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers()"> <ul id="user_list"></ul> <script src="/static/jquery-3.2.1.js"></script> <script> function getUsers() { $.ajax({ url:"http://www.s5.com:9000/user/", type:"GET", dataType:"JSONP", jsonp:"callback", jsonpCallback:'bbb' //相当于 http://www.s5.com:9000/user/?callback=bbb }) } function bbb(arg) { console.log(arg); for (var i = 0; i < arg.length; i++) { var tag = document.createElement("li"); tag.innerText = arg[i]; document.getElementById("user_list").appendChild(tag); } } </script> </body> </html>
四. cors
cors 跨站资源共享 #响应头加入 obj["Access-Control-Allow-Origin"] = "http://www.s4.com:8000" #仅这个域名可以访问 obj["Access-Control-Allow-Origin"] = "*" #所有域名都可以访问
a. www.s4.com 访问 www.s5.com,在响应头加入数据,同源策略就不生效
1. www.s4.com
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^cors/', views.cors), ]
from django.shortcuts import render,HttpResponse # Create your views here. def cors(request): return render(request,"core.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers()"> <ul id="user_list"></ul> <script src="/static/jquery-3.2.1.js"></script> <script> function getUsers() { $.ajax({ url:"http://www.s5.com:9000/user/", type:"GET", success:function (arg) { console.log(arg); console.log(typeof arg); for (var i = 0; i < arg.length; i++) { var tag = document.createElement("li"); tag.innerText = arg[i]; document.getElementById("user_list").appendChild(tag); } } }) } </script> </body> </html>
www.s5.com
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user', views.user),
]
from django.shortcuts import render,HttpResponse # Create your views here. import json def user(request): user_list = ["alex","egon","root"] user_list_str = json.dumps(user_list) obj = HttpResponse(user_list_str) obj["Access-Control-Allow-Origin"] = "http://www.s4.com:8000" return obj
b.预检request.method == "OPTIONS
1. www.s4.com
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^cors/', views.cors), ]
from django.shortcuts import render,HttpResponse # Create your views here. def cors(request): return render(request,"core.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers()"> <ul id="user_list"></ul> <script src="/static/jquery-3.2.1.js"></script> <script> function getUsers() { $.ajax({ url:"http://www.s5.com:9000/user/", type:"DELETE", success:function (arg) { console.log(arg); } }) } </script> </body> </html>
2. www.s5.com
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user', views.user),
]
from django.shortcuts import render,HttpResponse
# Create your views here.
import json
def user(request):
print(request.method)
if request.method == "OPTIONS":
obj = HttpResponse()
obj["Access-Control-Allow-Origin"] = "*"
obj["Access-Control-Allow-Methods"] = "DELETE"
return obj
obj = HttpResponse("..")
obj["Access-Control-Allow-Origin"] = "*"
return obj
五. 请求头
content-type content-type=“application/x-www-form-urlencoded” #默认值 格式为?name=yuan&pwd=123 content-type=“application/json” #向服务器发送的是json格式
六. Ajax 向后端发送数据
# 方式一: #前端 $.ajax({ url:'xx', type:'post', data: JSON.stringfy(pList), headers:{'Content-Type':'application/json'}, //contentType:'json', success:function(arg){ } }) 后端 # 使用request.body取值 json.loads(request.body.decode('utf-8')) # 方式二: #前端 $.ajax({ url:'xx', type:'post', data: {k1: JSON.stringfy(pList),'age':18} // k1="[....]"&age=18 success:function(arg){ } }) #后端 # 使用request.POST取值 json.loads(request.POST.get('k1'))