Ajax Ajax 即“Asynchronous Javascript And XML”(非同步 JavaScript 和 XML),是指⼀種創建互動式⽹⻚應⽤的⽹⻚開發技術。 Ajax 是⼀種⽤於創建快速動態⽹⻚的技術。 Ajax 是⼀種在⽆需重新載入整個⽹⻚的情況下,能夠更新部分⽹⻚的技術。 通過 ...
Ajax
Ajax 即“Asynchronous Javascript And XML”(非同步 JavaScript 和 XML),是指⼀種創建互動式⽹⻚應⽤的⽹⻚開發技術。
Ajax 是⼀種⽤於創建快速動態⽹⻚的技術。
Ajax 是⼀種在⽆需重新載入整個⽹⻚的情況下,能夠更新部分⽹⻚的技術。
通過在後臺與伺服器進⾏少量數據交換,Ajax 可以使⽹⻚實現非同步更新。這意味著可以在不重新載入整個⽹⻚的情況下,對⽹⻚的某部分進⾏更新。
傳統的⽹⻚(不使⽤ Ajax)如果需要更新內容,必須重載整個⽹⻚⻚⾯。
Ajax的優點:
非同步
:發送⼀個請求,不需要等待響應返回,隨時可以再發送下⼀個請求,即不需要等待。
局部刷新
:通過在後臺與伺服器進行少量數據交換,Ajax 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某部分進行更新。【傳統的網頁(不使用 Ajax)如果需要更新內容,必須重載整個網頁頁面。】
應用場景:
這是一個cnblog賬戶註冊界面,當我們在填寫昵稱的時候輸入regina,這個過程本身並沒有進行表單提交或者向伺服器發送請求,但是當游標離開這個input框之後,就會自動檢測了這裡面的內容,並且返回提示這個昵稱被占用了,而在圖二到圖三的過程當中,前端顯示為下圖,有一個刷新的過程,這個就是由於Ajax的局部刷新作用
這個過程中到底瀏覽器做了些什麼工作
我們篩選出XHR(XmlHttpResponse)類型的報文,看到其實瀏覽器是進行了一個checkDisplayName
的操作發送給了伺服器,然後伺服器的返回如下
json回顧
映射關係
Python | Json |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | True |
False | False |
None | Null |
dic = {
'user':"regina",
'age':22,
'is_married':True
}
print(json.dumps(dic),type(json.dumps(dic)))
{"user": "regina", "age": 22, "is_married": true} <class 'str'>
可以看到字典中的單引號全部變成了雙引號,True映射成了true
dic = [{'user':"regina"},{'age':20}]
print(repr(json.dumps(dic)))
dic = ({'user':"regina"},{'age':20})
print(repr(json.dumps(dic)))
'[{"user": "regina"}, {"age": 20}]'
'[{"user": "regina"}, {"age": 20}]'
列表和元組全變為了數組形式。
Ajax請求
首先確定一個概念就是Ajax請求不是表單提交,是JS代碼提交的,說明是要構建一個js代碼函數進行提交請求,所以這裡的submit是沒有用的,現在構建一段js代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<title>Title</title>
</head>
<body>
<h3>註冊界面</h3>
用戶名<input type="text" class="user"><br>
密碼 <input type="password"><br>
<input type="submit">
<script>
$(".user").blur(function () {
alert(123);
})
</script>
</body>
</html>
首先做一個測試,當游標移除用戶名時,會彈窗。
現在改為ajax請求的方式
<script>
$(".user").blur(function () {
$.ajax({
url:"http://127.0.0.1:8001/user/check/",
//請求方式預設get
})
})
</script>
然後我們設置好路由,在用戶名中輸入內容並離開框,看是否有新的請求發出。
我們的目的是要將input標簽里的用戶名傳給後端
$(".user").blur(function () {
$.ajax({
url:"http://127.0.0.1:8001/user/check/",
//請求方式預設get
data:{
"name" : $(".user").val()
},
})
})
經過測試,我們的數據已經傳回給了後端,並且也可以列印出來,現在要做的就是進行一個驗證再反饋到前端
def check(request):
ret = User.objects.filter(username=request.GET.get("name"))
if ret:
return HttpResponse("用戶已存在")
else:
return HttpResponse("")
這樣的話請求我們就做好了
$.ajax({
url:"http://127.0.0.1:8001/user/check/",
//請求方式預設get
data:{
"name" : $(".user").val()
},
//當相響應正常時觸發當函數
success:function (res) {
console.log(res)
}
})
success參數得到了後端響應回來的數據,並列印了出來,現在可以通過dom對象的操作,將返回內容添加到登陸界面進行提示。在用戶名標簽的後面添加一個span標簽,然後選中標簽進行添加內容
$(".err").html(res)
響應json數據
if ret:
res["exist"] = True
res["msg"] = "該用戶已存在"
return HttpResponse(json.dumps(res))
為什麼要用序列化,首先json可以發送很多的介面數據,並且如果要自己一個一個參數傳會很麻煩。按照正常邏輯,上圖代碼中我們首先寫好了json.dumps
將序列化轉為字元串,並且在html文件中進行反序列化,
success:function (res) {
console.log(res);
data = JSON.parse(res);
console.log(res);
if(data.exist){
$(".err").html(data.msg);
}
else{
$(".err").html(" ");
}
這樣我們也可以拿到序列化中的值,但是ajax好的一點就是當我們用JsonResponse(res)
,在html中我們可以直接調用參數,不需要再進行parse反序列化。
練習實例
用ajax實現一個加法
<input type="text" class="add n1"> + <input type="text" class="add n2"> = <input type="text" class="add ans" > <button class="btn">計算</button>
$(".btn").click(function () {
$.ajax({
url:"http://127.0.0.1:8001/user/add/",
type:"post",
data:{
"num1":$(".n1").val(),
"num2":$(".n2").val(),
},
success: function(res){
$(".ans").val(res);
}
})
})
def add(request):
num1 = int(request.POST.get("num1"))
num2 = int(request.POST.get("num2"))
return HttpResponse(str(num1+num2))
非同步
同步請求指的是當我訪問url時,如果在視圖函數當中添加一個睡眠,讓伺服器等待了5秒,
def reg(request):
time.sleep(5)
return render(request,"reg.html")
那麼相應的,客戶端如圖所示,也需要等5秒才能進入頁面。
但是非同步指的是當我在ajax請求的視圖函數當中添加一個睡眠,但其他的請求函數不做任何改變的話,那麼這個睡眠等待只會影響這一個ajax請求,其他的正常工作。
def check(request):
ret = User.objects.filter(username=request.GET.get("name"))
res = {"exist":False, "msg":""}
time.sleep(5)
if ret:
res["exist"] = True
res["msg"] = "該用戶已存在"
return JsonResponse(res)
def add(request):
num1 = int(request.POST.get("num1"))
num2 = int(request.POST.get("num2"))
return HttpResponse(str(num1+num2))
同源策略
之前我們一直輸入的是ip地址和埠號以及路由,但是現在直接本地文件的形式打開網頁,並且我們代碼的路由依然是伺服器地址,但是依然會報錯。
但問題就是他這個路由請求沒有問題,我們可以在後端把1和2都列印出來,但是無法進行響應。
這是因為瀏覽器
的同源策略導致的
同源策略概念
是一種約定,是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能都會被影響。可以說web是構建在同源策略之上的,瀏覽器只是針對同源策略的一種實現。
同源策略(same origin policy)是netScape(網景)提出的一個安全策略,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。具體表現為瀏覽器在執行腳本前,會判斷腳本是否與打開的網頁是同源的,判斷協議、功能變數名稱、埠是否都相同,相同則表示同源。其中一項不相同就表示跨域訪問。會在控制台報一個CORS異常,目的是為了保護本地數據不被JavaScript代碼獲取回來的數據污染,因此攔截的是客戶端發出的請求回來的數據接收,即請求發送了,伺服器響應了,但是無法被瀏覽器接收。
解決方案:跨域資源共用(CORS)
服務端設置,可以允許其他源訪問服務端資源,藉助nodejs實現。
res = HttpResponse(str(num1+num2))
res["Access-Control-Allow-Origin"] = "*"
return res
headers里會有我們添加的那句話,識別到這句話就不會攔截了。
Cors有兩種請求,一種是簡單請求,一種是非簡單請求,只要滿足以下兩種要求之一就是簡單請求
(一)請求方法是下列三個之一:
GET
POST
HEAD
(二) HTTP的頭部信息不超過以下幾種欄位:
- Accept
- Accept-language
- Content-language
- Last-Event-ID
- Content-Type:只限於三個值【application/x-www-form-urlencoded、multipart/form-data、text/plain】
本文來自博客園,作者:ivanlee717,轉載請註明原文鏈接:https://www.cnblogs.com/ivanlee717/p/16849676.html