jax在前端開發中有著舉足輕重的地位,關于Ajax的使用和注意事項一直是一個重要的話題,借此機會,本文希望對Ajax做一個全面的總結,徹底揭開Ajax的神秘面紗。
Ajax(Asynchronous JavaScript and XML),可以理解為JavaScript執行異步網絡請求。通俗的理解的話就是,如果沒有Ajax技術,改變網頁的一小部分(哪怕是一行文字、一張圖片)都需要重新加載一次整個頁面,而有了Ajax之后,就可以實現在網頁不跳轉不刷新的情況下,在網頁后臺提交數據,部分更新頁面內容。
XMLHttpRequest 對象用于在后臺與服務器交換數據,能夠在不重新加載頁面的情況下更新網頁,在頁面已加載后從服務器請求數據,在頁面已加載后從服務器接收數據,在后臺向服務器發送數據。所以XMLHttpRequest對象是Ajax技術的核心所在。
創建 XMLHttpRequest對象——>打開請求地址,初始化數據——>發送請求數據——>監聽回調函數狀態——>收到服務器返回的應答結果。
下面用具體的代碼進行解釋:
var xmlhttp; function loadXMLDoc(url) { xmlhttp=null; if (window.XMLHttpRequest) {// code for all new browsers xmlhttp=new XMLHttpRequest();//在這里創建 XMLHttpRequest對象 } else if (window.ActiveXObject) {// code for IE5 and IE6 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } if (xmlhttp!=null) { xmlhttp.open("GET",url,true); //請求的方式和請求地址 xmlhttp.send(null);//發送請求 xmlhttp.onreadystatechange=state_Change;//監聽回調函數 } else { alert("Your browser does not support XMLHTTP."); } } function state_Change() //這里是回調函數 { if (xmlhttp.readyState==4&&xmlhttp.status==200) //當滿足這兩個條件時表示請求成功,完成響應 4="loaded", 200=OK { var data=xmlhttp.responseText; //拿到服務器返回的數據 // ...our code here...在這里進行數據返回后的操作 }else { alert("Problem retrieving XML data"); } }
(1).open() 的第三個參數中使用了 "true",該參數規定請求是否異步處理,默認是異步。True 表示腳本會在 send() 方法之后繼續執行,而不等待來自服務器的響應。
(2).關于readyState
(3).關于status 由服務器返回的 HTTP 狀態代碼,200 表示成功,而 404 表示 "Not Found" 錯誤。當 readyState 小于 3 的時候讀取這一屬性會導致一個異常。(后面會有http狀態碼的詳細解讀)
JQuery對原生Ajax做了很好的封裝,使用起來非常簡單方便,具體的很多方法如 $.ajax,$.post, $.get, $.getJSON等能根據不同需要進行調用,寫法更加簡潔,但是為了兼顧各個方法在這里我以一個通用的方法 $.ajax為例做一個簡單的解析,按照下面的模式寫好各個參數,就能成功進行Ajax的請求了,可能在實際中使用 $.post, $.get 這兩個方法使用比較多,但是理解$.ajax 這個通用的方法能對封裝原理有很好的認識。
$.ajax({ type: //數據的提交方式:get和post url: //請求地址 async: //是否支持異步刷新,默認是true data: //需要提交的數據 dataType: //服務器返回數據的類型,例如xml,String,Json等 success:function(data){ } //請求成功后的回調函數,參數data就是服務器返回的數據 error:function(data){ } //請求失敗后的回調函數,根據需要可以不寫,一般只寫上面的success回調函數 })
作為Ajax最常用的兩種數據提交方式,GET和POST有著自己的特點和適用場景,正確區分GET和POST的不同并根據實際需要進行選用在開發中十分重要,簡單但是關鍵!
先上一張GET 和 POST的比較圖,從這張圖中可以看出兩者之間的差別:
從表格中拎出關鍵點: 1.傳遞數據的方式不同:get是直接把請求數據放在url的后面,是可見的,post的請求數據不會顯示在url中,是不可見的。 2.數據長度和數據類型的差異:get有數據長度的的限制,且數據類型只允許ASCII字符,post在這兩方面都沒有限制。 3.安全性的差異:get不安全,post更安全。
由此得出的兩者的使用場景:get使用較方便,適用于頁面之間非敏感數據的簡單傳值,post使用較為安全,適用于向服務器發送密碼、token等敏感數據。
JQuery封裝的Ajax回調函數中,success、error、complete是最常用的三個,其中,success和error很好區別,一個是請求成功調用的,另一個是請求失敗調用的,從字面上就可以理解。但是success和complete容易混淆,在這里特別做一個說明:
success:請求成功后回調函數。
complete:請求完成后回調函數 (請求成功或失敗時均調用)。
注意到括號里面了嗎,沒錯,區別就在于complete只要請求完成,不論是成功還是失敗均會調用。也就是說如果調用了success,一定會調用complete;反過來調用了complete,不一定會調用success。(狀態碼404、403、301、302...都會進入complete,只要不出錯就會調用)
Ajax中的是 "x" 指的就是XML。
xml:可擴展標記語言,標準通用標記語言的子集,是一種用于標記電子文件使其具有結構性的標記語言。
xml作為一種數據交互格式,廣泛用在計算機領域,然而,隨著json的發展,json以其明顯的優勢已經漸漸取代了xml成為現在數據交互格式的標準,所以在這里,想強調的是,json現在是主流的數據交互格式,前后端的交互標準,無論是前端提交給后臺的數據,還是后臺返回給前端的數據,都最好統一為json格式,各自接收到數據后再解析數據即可供后續使用。所以 "Ajax" 實際上已經發展為 "Ajaj"
json 和 jsonp 看起來只相差了一個 “p” ,然而實際上根本不是一個東西,千萬別以為是差不多的兩個概念。
json:(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。
jsonp:一種借助 <script> 元素解決主流瀏覽器的跨域數據訪問問題的方式。
ajax很好,但不是萬能的,ajax的請求與訪問同樣會受到瀏覽器同源策略的限制,不能訪問不同主域中的地址。所以,為了解決這一問題,實現跨域訪問,有很多種方式,上述提到的jsonp就是一種流行的方式,還有其他一些方式,我在這里就不展開說了,只是想說明ajax的使用也是有條件的,任何技術的實現都不會是沒有限制的。跨域訪問時一個很重要的知識點,之前專門寫過一篇關于跨域訪問的總結,還挺詳細的,可以移步查看: javascript中實現跨域的方式總結
前面提到的"200"、"404"只是http狀態碼中常見的兩個,當瀏覽者訪問一個網頁時,瀏覽者的瀏覽器會向網頁所在服務器發出請求。當瀏覽器接收并顯示網頁前,此網頁所在的服務器會返回一個包含HTTP狀態碼的信息頭(server header)用以響應瀏覽器的請求。
需要掌握的常見http狀態碼大致有以下一些:
101:切換協議,服務器根據客戶端的請求切換協議 **200:請求成功。一般用于GET與POST請求** **301:永久重定向** **302:臨時重定向** 303:與301類似。使用GET和POST請求查看 **304:請求資源未修改,使用緩存** 307:與302類似。使用GET請求重定向 **404:客戶端請求失敗** 408:請求超時 **500:內部服務器錯誤,無法完成請求** 505:服務器不支持請求的HTTP協議的版本,無法完成處理
http請求中的一個重要關注點就是請求頭和響應頭的內容,從這兩個頭文件中可以看出很多東西,當我們用發送一個ajax請求的時候,如果沒有達到預期的效果,那么就需要打開瀏覽器的調試工具,從NetWork中找到相應的ajax請求,再通過查看請求頭和響應頭的信息,大體會知道這次請求的結果是怎么樣的,結合響應的主體內容,可以很快找到問題。所以學會看http的頭文件信息是前端開發中必須掌握的一個技能,下面就來看看具體的頭文件信息。
首先隨便上一張sf中的完成一個搜索結果的http請求,可以從圖中的右側清楚看到請求頭和響應頭的內容,包括了很多個字段信息,這些字段信息就是我們需要掌握的知識點,下面挑出其中的重點字段進行分析。
Accept:客戶端支持的數據類型 Accept-Charset:客戶端采用的編碼 Accept-Encoding:客戶端支持的數據壓縮格式 Accept-Language:客戶端的語言環境 Cookie:客服端的cookie Host:請求的服務器地址 Connection:客戶端與服務連接類型 If-Modified-Since:上一次請求資源的緩存時間,與Last-Modified對應 If-None-Match:客戶段緩存數據的唯一標識,與Etag對應 Referer:發起請求的源地址。
content-encoding:響應數據的壓縮格式。 content-length:響應數據的長度。 content-language:語言環境。 content-type:響應數據的類型。 Date:消息發送的時間 Age:經過的時間 Etag:被請求變量的實體值,用于判斷請求的資源是否發生變化 Expires:緩存的過期時間 Last-Modified:在服務器端最后被修改的時間 server:服務器的型號
Pragma:是否緩存(http1.0提出) Cache-Control:是否緩存(http1.1提出)
(1) 強制緩存 expire 和 cache-control
(2) 對比緩存 Last-Modified 和 If-Modified-Since Etag 和 If-None-Match
安全問題,對一些網站攻擊,如csrf、xxs、sql注入等不能很好地防御。
* JSON 使用 JavaScript 語法來描述數據對象,但是 JSON 仍然獨立于語言和平臺。JSON 解析器和 JSON 庫支持許多不同的編程語言。
合格的json對象:
["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["張三", "李四"] }
[ { "name": "張三"}, {"name": "李四"} ]
不合格的json對象:
{ name: "張三", 'age': 32 } // 屬性名必須使用雙引號
[32, 64, 128, 0xFFF] // 不能使用十六進制值
{ "name": "張三", "age": undefined } // 不能使用undefined
{ "name": "張三",
"birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
"getName": function() {return this.name;} // 不能使用函數和日期對象
}
JavaScript中關于JSON對象和字符串轉換的兩個方法:
JSON.parse(): 用于將一個 JSON 字符串轉換為 JavaScript 對象
JSON.parse('{"name":"run1"}');
JSON.parse('{name:"run1"}') ; // 錯誤
JSON.parse('[18,undefined]') ; // 錯誤
JSON.stringify(): 用于將 JavaScript 值轉換為 JSON 字符串。
JSON.stringify({"name":"run1"})
JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁瑣笨重的 XML 格式。
JSON 格式有兩個顯著的優點:書寫簡單,一目了然;符合 JavaScript 原生語法,可以由解釋引擎直接處理,不用另外添加解析代碼。所以,JSON迅速被接受,已經成為各大網站交換數據的標準格式,并被寫入ECMAScript 5,成為標準的一部分。
XML和JSON都使用結構化方法來標記數據,下面來做一個簡單的比較。
用XML表示中國部分省市數據如下:
<?xml version="1.0" encoding="utf-8"?>
<country>
<name>中國</name>
<province>
<name>黑龍江</name>
<cities>
<city>哈爾濱</city>
<city>大慶</city>
</cities>
</province>
<province>
<name>廣東</name>
<cities>
<city>廣州</city>
<city>深圳</city>
<city>珠海</city>
</cities>
</province>
<province>
<name>臺灣</name>
<cities>
<city>臺北</city>
<city>高雄</city>
</cities>
</province>
<province>
<name>新疆</name>
<cities>
<city>烏魯木齊</city>
</cities>
</province>
</country>
用JSON表示如下
{
"name": "中國",
"province": [{
"name": "黑龍江",
"cities": {
"city": ["哈爾濱", "大慶"]
}
}, {
"name": "廣東",
"cities": {
"city": ["廣州", "深圳", "珠海"]
}
}, {
"name": "臺灣",
"cities": {
"city": ["臺北", "高雄"]
}
}, {
"name": "新疆",
"cities": {
"city": ["烏魯木齊"]
}
}]
}
由上面的兩段代碼可以看出,JSON 簡單的語法格式和清晰的層次結構明顯要比 XML 容易閱讀,并且在數據交換方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得節約傳輸數據所占用的帶寬。
AJAX(Asynchronous Javascript And XML)翻譯成中文就是“異步Javascript和XML”。即使用Javascript語言與服務器進行異步交互,傳輸的數據為XML(當然,傳輸的數據不只是XML)。
AJAX除了異步的特點外,還有一個就是:瀏覽器頁面局部刷新;(這一特點給用戶的感受是在不知不覺中完成請求和響應過程)
示例:
頁面輸入兩個整數,通過AJAX傳輸到后端計算出結果并返回。
HTML部分代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AJAX局部刷新實例</title>
</head>
<body>
<input type="text" id="i1">+
<input type="text" id="i2">=<input type="text" id="i3">
<input type="button" value="AJAX提交" id="b1">
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/",
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val()},
success:function (data) {
$("#i3").val(data);
}
})
})
</script>
</body>
</html>
views.py
def ajax_demo1(request):
return render(request, "ajax_demo1.html")
def ajax_add(request):
i1=int(request.GET.get("i1"))
i2=int(request.GET.get("i2"))
ret=i1 + i2
return JsonResponse(ret, safe=False)
urls.py
urlpatterns=[
...
url(r'^ajax_add/', views.ajax_add),
url(r'^ajax_demo1/', views.ajax_demo1),
...
]
$.ajax({
url:"", // 控制往哪里提交
type:"POST", // 請求的方法
data:{}, // 請求的參數
success:function(arg){
// 收到響應之后要做的事
}
})
搜索引擎根據用戶輸入的關鍵字,自動提示檢索關鍵字。
還有一個很重要的應用場景就是注冊時候的用戶名的查重。
其實這里就使用了AJAX技術!當文件框發生了輸入變化時,使用AJAX技術向服務器發送一個請求,然后服務器會把查詢到的結果響應給瀏覽器,最后再把后端返回的結果展示出來。
當輸入用戶名后,把光標移動到其他表單項上時,瀏覽器會使用AJAX技術向服務器發出請求,服務器會查詢名為lemontree7777777的用戶是否存在,最終服務器返回true表示名為lemontree7777777的用戶已經存在了,瀏覽器在得到結果后顯示“用戶名已被注冊!”。
優點
最基本的jQuery發送AJAX請求示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ajax test</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<button id="ajaxTest">AJAX 測試</button>
<script>
$("#ajaxTest").click(function () {
$.ajax({
url: "/ajax_test/",
type: "POST",
data: {username: "Q1mi", password: 123456},
success: function (data) {
alert(data)
}
})
})
</script>
</body>
</html>
views.py
def ajax_test(request):
user_name=request.POST.get("username")
password=request.POST.get("password")
print(user_name, password)
return HttpResponse("OK")
$.ajax參數
data參數中的鍵值對,如果值值不為字符串,需要將其轉換成字符串類型。
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/",
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
success:function (data) {
$("#i3").val(data);
}
})
})
方式1
通過獲取隱藏的input標簽中的csrfmiddlewaretoken值,放置在data中發送。
$.ajax({
url: "/cookie_ajax/",
type: "POST",
data: {
"username": "rum2",
"password": 123456,
"csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val() // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中
},
success: function (data) {
console.log(data);
}
})
通過獲取返回的cookie中的字符串 放置在請求頭中發送。
注意:需要引入一個jquery.cookie.js插件。
$.ajax({
url: "/cookie_ajax/",
type: "POST",
headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 從Cookie取csrf_token,并設置ajax請求頭
data: {"username": "rum", "password": 123456},
success: function (data) {
console.log(data);
}
})
或者用自己寫一個getCookie方法:
function getCookie(name) {
var cookieValue=null;
if (document.cookie && document.cookie !=='') {
var cookies=document.cookie.split(';');
for (var i=0; i < cookies.length; i++) {
var cookie=jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1)===(name + '=')) {
cookieValue=decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken=getCookie('csrftoken');
每一次都這么寫太麻煩了,可以使用$.ajaxSetup()方法為ajax請求統一設置。
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Django內置的serializers
def books_json(request):
book_list=models.Book.objects.all()[0:10]
from django.core import serializers
ret=serializers.serialize("json", book_list)
return HttpResponse(ret)
我們的數據中經常有日期時間,也就是datetime對象,而json.dumps是無法處理這樣在類型的,那就需要通過自定義處理器來做擴展,如下:
class JsonCustomEncoder(json.JSONEncoder):
"""
自定義一個支持序列化時間格式的類
"""
def default(self, o):
if isinstance(o, datetime):
return o.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(o, date):
return o.strftime("%Y-%m-%d")
else:
return json.JSONEncoder.default(self, o)
def books_json(request):
book_list=models.Book.objects.all().values_list("title", "publish_date")
ret=json.dumps(list(book_list), cls=JsonCustomEncoder)
return HttpResponse(ret)
Bootstrap-sweetalert
https://github.com/lipis/bootstrap-sweetalert
$(".btn-danger").on("click", function () {
swal({
title: "你確定要刪除嗎?",
text: "刪除可就找不回來了哦!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "刪除",
cancelButtonText: "取消",
closeOnConfirm: false
},
function () {
var deleteId=$(this).parent().parent().attr("data_id");
$.ajax({
url: "/delete_book/",
type: "post",
data: {"id": deleteId},
success: function (data) {
if (data.status===1) {
swal("刪除成功!", "你可以準備跑路了!", "success");
} else {
swal("刪除失敗", "你可以再嘗試一下!", "error")
}
}
})
});
})
#科技##軟件開發##python#
AJAX 即“Asynchronous Javascript And XML”(異步 JavaScript 和 XML),是指一種創建交互式網頁應用的網頁開發 技術。
ajax 是一種瀏覽器通過 js 異步發起請求,局部更新頁面的技術。
Ajax 請求的局部更新,瀏覽器地址欄不會發生變化
局部更新不會舍棄原來頁面的內容
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
// 在這里使用 javaScript 語言發起 Ajax 請求,訪問服務器 AjaxServlet 中 javaScriptAjax
function ajaxRequest() {
// 我們首先要創建 XMLHttpRequest
var xmlhttprequest=new XMLHttpRequest();
// 調用 open 方法設置請求參數
xmlhttprequest.open("GET","http://localhost:8080/Test/ajaxServlet?action=javaScriptAj
ax",true)
// 在 send 方法前綁定 onreadystatechange 事件,處理請求完成后的操作。
xmlhttprequest.onreadystatechange=function(){
if (xmlhttprequest.readyState==4 && xmlhttprequest.status==200) {
var jsonObj=JSON.parse(xmlhttprequest.responseText);
// 把響應的數據顯示在頁面上
document.getElementById("div01").innerHTML=" 編號:" + jsonObj.id + " , 姓名:" +
jsonObj.name;
}
}
// 調用 send 方法發送請求
xmlhttprequest.send();
}
</script>
</head>
<body>
<button onclick="ajaxRequest()">ajax request</button>
<div id="div01">
</div>
</body>
</html>
$.ajax 方法
url 表示請求的地址
type 表示請求的類型 GET 或 POST 請求
data 表示發送給服務器的數據
格式有兩種:
一:name=value&name=value
二:{key:value}
success 請求成功,響應的回調函數
dataType 響應的數據類型
常用的數據類型有:
text 表示純文本
xml 表示 xml 數據
json 表示 json 對象
$("#ajaxBtn").click(function(){
$.ajax({
url:"http://localhost:8080/Test/ajaxServlet",
// data:"action=jQueryAjax",
data:{action:"jQueryAjax"},
type:"GET",
success:function (data) {
// alert(" 服務器返回的數據是: " + data);
// var jsonObj=JSON.parse(data);
$("#msg").html(" 編號:" + data.id + " , 姓名:" + data.name);
},
dataType : "json"
});
});
方法和.post 方法
url 請求的 url 地址
data 發送的數據
callback 成功的回調函數
type 返回的數據類型
// ajax--get 請求
$("#getBtn").click(function(){
$.get("http://localhost:8080/Test/ajaxServlet","action=jQueryGet",function (data) {
$("#msg").html(" get 編號:" + data.id + " , 姓名:" + data.name);
},"json");
});
// ajax--post 請求
$("#postBtn").click(function(){
$.post("http://localhost:8080/Test/ajaxServlet","action=jQueryPost",function (data)
{
$("#msg").html(" post 編號:" + data.id + " , 姓名:" + data.name);
},"json");
});
$.getJSON 方法
url 請求的 url 地址
data 發送給服務器的數據
callback 成功的回調函數
// ajax--getJson 請求
$("#getJSONBtn").click(function(){
$.getJSON("http://localhost:8080/Test/ajaxServlet","action=jQueryGetJSON",function
(data) {
$("#msg").html(" getJSON 編號:" + data.id + " , 姓名:" + data.name);
});
});
表單序列化 serialize() serialize()可以把表單中所有表單項的內容都獲取到,并以 name=value&name=value 的形式進行拼接。
// ajax 請求
$("#submit").click(function(){
// 把參數序列化
$.getJSON("http://localhost:8080/Test/ajaxServlet","action=jQuerySerialize&" +
$("#form01").serialize(),function (data) {
$("#msg").html(" Serialize 編號:" + data.id + " , 姓名:" + data.name);
});
});
歡迎關注公眾號:愚生淺末。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。