一、概述javascript
AJAX 是一種在無需從新加載整個網頁的狀況下,可以更新部分網頁的技術。AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步Javascript和XML」。即:使用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML,好比還有JSON)。html
二、使用場景前端
三、優缺點java
一、過程和請求相關jquery
二、經過JavaScript實現Ajax之無後臺交互web
<html>
<head>
<script type="text/javascript">
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","/ajax/test1.txt",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv"><h2>Let AJAX change this text</h2></div>
<button type="button" onclick="loadXMLDoc()">經過 AJAX 改變內容</button>
</body>
</html>
三、經過JavaScript實現Ajax之與後臺交互ajax
經過Django實現,其實惟一區別就是在open的時候,把URL修改爲Django的一個URL便可,包括GET和POST方法的URL。json
a、urls.py文件後端
urlpatterns = [
url(r'^ajax_get',views.ajax_get),
url(r'^ajax_post',views.ajax_post)
]
b、views.py文件api
def ajax_get(req):
return render(req,'ajax_get.html')
def ajax_post(req):
if req.method=='POST':
print req.POST
else:
print req.GET
return HttpResponse('ajax_post')
c、ajax_get.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>測試ajax的GET方法</title>
<script>
function loadXMLDoc()
{
var xmlhttp; //定義局部變量xmlhttp
if (window.XMLHttpRequest) //XMLHttpRequet對象用於和服務器交互數據。
{
// IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼
xmlhttp=new XMLHttpRequest();
}
else{
// IE6, IE5 瀏覽器執行代碼
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//偵聽
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
//POST方法
xmlhttp.open("POST","./ajax_post",true);
//GET方法
//xmlhttp.open("GET","./user_info",true);
//設置頭部信息
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//POST method發送
xmlhttp.send("name=xuequn");
//GET method發送
//xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改該文本內容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改</button>
</body>
</html>
d、測試結果
GET方法:
POST方法:
一、兩個快捷API
<1>$.get(url, [data], [callback], [type])
<2>$.post(url, [data], [callback], [type])
url:請求的URL
data:發送的數據
callback:回調函數,前端發送數據給後端以後,後端返回數據給前端,前端接受到的數據
type:text|html|json|script
二、兩個不經常使用API
getJSON(url,data,callback)
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$.getJSON("/example/jquery/demo_ajax_json.js",function(result){
$.each(result, function(i, field){
$("p").append(field + " ");
});
});
});
});
</script>
</head>
<body>
<button>得到 JSON 數據</button>
<p></p>
</body>
</html>
///example/jquery/demo_ajax_json.js
{
"firstName": "Bill",
"lastName": "Gates",
"age": 60
}
getScript( url ,callback ])
jQuery.getScript("http://dev.jquery.com/view/trunk/plugins/color/jquery.color.js",
function(){
$("#go").click(function(){
$(".block").animate( { backgroundColor: 'pink' }, 1000)
.animate( { backgroundColor: 'blue' }, 1000);
});
});
三、最經常使用的方法
$.ajax()
$(function(){
$('#send').click(function(){
$.ajax({
type: "GET",
url: "test.json",
data: {username:$("#username").val(), content:$("#content").val()},
dataType: "json",
success: function(data){
$('#resText').empty(); //清空resText裏面的全部內容
var html = '';
$.each(data, function(commentIndex, comment){
html += '<div class="comment"><h6>' + comment['username']
+ ':</h6><p class="para"' + comment['content']
+ '</p></div>';
});
$('#resText').html(html);
}
});
});
});
ajax的參數
1.url:
要求爲String類型的參數,(默認爲當前頁地址)發送請求的地址。
2.type:
要求爲String類型的參數,請求方式(post或get)默認爲get。注意其餘http請求方法,例如put和delete也可使用,但僅部分瀏覽器支持。
3.timeout:
要求爲Number類型的參數,設置請求超時時間(毫秒)。此設置將覆蓋$.ajaxSetup()方法的全局設置。
4.async:
要求爲Boolean類型的參數,默認設置爲true,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲false。注意,同步請求將鎖住瀏覽器,用戶其餘操做必須等待請求完成才能夠執行。
5.cache:
要求爲Boolean類型的參數,默認爲true(當dataType爲script時,默認爲false),設置爲false將不會從瀏覽器緩存中加載請求信息。
6.data:
要求爲Object或String類型的參數,發送到服務器的數據。若是已經不是字符串,將自動轉換爲字符串格式。get請求中將附加在url後。防止這種自動轉換,能夠查看processData選項。
對象必須爲key/value格式,例如{foo1:"bar1",foo2:"bar2"}轉換爲&foo1=bar1&foo2=bar2。若是是數組,JQuery將自動爲不一樣值對應同一個名稱。例如{foo:["bar1","bar2"]}轉換爲&foo=bar1&foo=bar2。
7.dataType:
要求爲String類型的參數,預期服務器返回的數據類型。若是不指定,JQuery將自動根據http包mime信息返回responseXML或responseText,並做爲回調函數參數傳遞。可用的類型以下:
xml:返回XML文檔,可用JQuery處理。
html:返回純文本HTML信息;包含的script標籤會在插入DOM時執行。
script:返回純文本JavaScript代碼。不會自動緩存結果。除非設置了cache參數。注意在遠程請求時(不在同一個域下),全部post請求都將轉爲get請求。
json:返回JSON數據。
jsonp:JSONP格式。使用SONP形式調用函數時,例如myurl?callback=?,JQuery將自動替換後一個「?」爲正確的函數名,以執行回調函數。
text:返回純文本字符串。
8.beforeSend:
要求爲Function類型的參數,發送請求前能夠修改XMLHttpRequest對象的函數,例如添加自定義HTTP頭。在beforeSend中若是返回false能夠取消本次ajax請求。XMLHttpRequest對象是唯一的參數。
function(XMLHttpRequest){
this; //調用本次ajax請求時傳遞的options參數
}
9.complete:
要求爲Function類型的參數,請求完成後調用的回調函數(請求成功或失敗時均調用)。參數:XMLHttpRequest對象和一個描述成功請求類型的字符串。
function(XMLHttpRequest, textStatus){
this; //調用本次ajax請求時傳遞的options參數
}
10.success:要求爲Function類型的參數,請求成功後調用的回調函數,有兩個參數。
(1)由服務器返回,並根據dataType參數進行處理後的數據。
(2)描述狀態的字符串。
function(data, textStatus){
//data多是xmlDoc、jsonObj、html、text等等
this; //調用本次ajax請求時傳遞的options參數
}
11.error:
要求爲Function類型的參數,請求失敗時被調用的函數。該函數有3個參數,即XMLHttpRequest對象、錯誤信息、捕獲的錯誤對象(可選)。ajax事件函數以下:
function(XMLHttpRequest, textStatus, errorThrown){
//一般狀況下textStatus和errorThrown只有其中一個包含信息
this; //調用本次ajax請求時傳遞的options參數
}
12.contentType:
要求爲String類型的參數,當發送信息至服務器時,內容編碼類型默認爲"application/x-www-form-urlencoded"。該默認值適合大多數應用場合。
13.dataFilter:
要求爲Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,
type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理後的數據
return data;
}
14.dataFilter:
要求爲Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,
type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理後的數據
return data;
}
15.global:
要求爲Boolean類型的參數,默認爲true。表示是否觸發全局ajax事件。設置爲false將不會觸發全局ajax事件,ajaxStart或ajaxStop可用於控制各類ajax事件。
16.ifModified:
要求爲Boolean類型的參數,默認爲false。僅在服務器數據改變時獲取新數據。服務器數據改變判斷的依據是Last-Modified頭信息。默認值是false,即忽略頭信息。
17.jsonp:
要求爲String類型的參數,在一個jsonp請求中重寫回調函數的名字。該值用來替代在"callback=?"這種GET或POST請求中URL參數裏的"callback"部分,
例如{jsonp:'onJsonPLoad'}會致使將"onJsonPLoad=?"傳給服務器。
18.username:
要求爲String類型的參數,用於響應HTTP訪問認證請求的用戶名。
19.password:
要求爲String類型的參數,用於響應HTTP訪問認證請求的密碼。
20.processData:
要求爲Boolean類型的參數,默認爲true。默認狀況下,發送的數據將被轉換爲對象(從技術角度來說並不是字符串)以配合默認內容類型"application/x-www-form-urlencoded"。
若是要發送DOM樹信息或者其餘不但願轉換的信息,請設置爲false。
21.scriptCharset:
要求爲String類型的參數,只有當請求時dataType爲"jsonp"或者"script",而且type是GET時纔會用於強制修改字符集(charset)。一般在本地和遠程的內容編碼不一樣時使用。
四、Django中設定狀態碼
HttpResponse.status_code = 400 //手動設定返回的狀態碼爲400
瀏覽器有一個很重要的概念——同源策略(Same-Origin Policy)。所謂同源是指,域名,協議,端口相同。不一樣源的客戶端腳本(javascript、ActionScript)在沒明確受權的狀況下,不能讀寫對方的資源。
簡單的來講,瀏覽器容許包含在頁面A的腳本訪問第二個頁面B的數據資源,這一切是創建在A和B頁面是同源的基礎上。
若是Web世界沒有同源策略,當你登陸淘寶帳號並打開另外一個站點時,這個站點上的JavaScript能夠跨域讀取你的任意帳號的數據,這樣整個Web世界就無隱私可言了。
4.2 問題出現
在同源策略下,好比我在URL01:http://localhost/user_manager/test_jsonp/上獲取https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse的數據時,就是屬於跨域了,此時會出現問題:
代碼以下:重點在open裏面的URL,是屬於跨域的行爲。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax</title>
</head>
<body>
<div id="mydiv">
<button id="btn">點擊</button>
</div>
</body>
<script type="text/javascript">
window.onload = function() {
var oBtn = document.getElementById('btn');
oBtn.onclick = function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert( xhr.responseText );
}
};
xhr.open('get', 'https://api.douban.com/v2/book/search?q=javascript&count=1', true);
xhr.send();
};
};
</script>
</html>
上述程序運行時會報錯:
4.3 JSONP介紹
JSONP 是 JSON with padding(填充式 JSON 或參數式 JSON)的簡寫。
JSONP實現跨域請求的原理簡單的說,就是動態建立<script>
標籤,而後利用<script>
的src 不受同源策略約束來跨域獲取數據。
JSONP 由兩部分組成:回調函數和數據。回調函數是當響應到來時應該在頁面中調用的函數。回調函數的名字通常是在請求中指定的。而數據就是傳入回調函數中的 JSON 數據。
其實網上關於JSONP的講解有不少,大概總結以下:
一、一個衆所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一概不許;
二、不過咱們又發現,Web頁面上調用js文件時則不受是否跨域的影響(不只如此,咱們還發現凡是擁有"src"這個屬性的標籤都擁有跨域的能力,好比<script>、<img>、<iframe>);
三、因而能夠判斷,當前階段若是想經過純web端(ActiveX控件、服務端代理、屬於將來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件裏,供客戶端調用和進一步處理;
四、恰巧咱們已經知道有一種叫作JSON的純字符數據格式能夠簡潔的描述複雜數據,更妙的是JSON還被js原生支持,因此在客戶端幾乎能夠爲所欲爲的處理這種格式的數據;
五、這樣子解決方案就呼之欲出了,web客戶端經過與調用腳本如出一轍的方式,來調用跨域服務器上動態生成的js格式文件(通常以JSON爲後綴),顯而易見,服務器之因此要動態生成JSON文件,目的就在於把客戶端須要的數據裝入進去。
六、客戶端在對JSON文件調用成功以後,也就得到了本身所需的數據,剩下的就是按照本身需求進行處理和展示了,這種獲取遠程數據的方式看起來很是像AJAX,但其實並不同。
七、爲了便於客戶端使用數據,逐漸造成了一種非正式傳輸協議,人們把它稱做JSONP,該協議的一個要點就是容許用戶傳遞一個callback參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,這樣客戶端就能夠隨意定製本身的函數來自動處理返回數據了。
若是對於callback參數如何使用還有些模糊的話,咱們後面會有具體的實例來說解。
4.4 JavaScript實現跨域
一、咱們知道,哪怕跨域js文件中的代碼(固然指符合web腳本安全策略的),web頁面也是能夠無條件執行的,好比img中的src指定的圖片地址能夠是網上任意圖片。
遠程服務器remoteserver.com根目錄下有個remote.js文件代碼以下:
alert('我是遠程文件');
本地服務器localserver.com下有個jsonp.html頁面代碼以下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>
複製代碼
毫無疑問,頁面將會彈出一個提示窗體,顯示跨域調用成功。
二、如今咱們在jsonp.html頁面定義一個函數,而後在遠程remote.js中傳入數據進行調用。
jsonp.html頁面代碼以下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函數,能夠被跨域的remote.js文件調用,遠程js帶來的數據是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>
remote.js文件代碼以下:
localHandler({"result":"我是遠程js帶來的數據"});
運行以後查看結果,頁面成功彈出提示窗口,顯示本地函數被跨域的遠程js調用成功,而且還接收到了遠程js帶來的數據。很欣喜,跨域遠程獲取數據的目的基本實現了,可是又一個問題出現了,我怎麼讓遠程js知道它應該調用的本地函數叫什麼名字呢?畢竟是jsonp的服務者都要面對不少服務對象,而這些服務對象各自的本地函數都不相同啊?咱們接着往下看。
三、聰明的開發者很容易想到,只要服務端提供的js腳本是動態生成的就好了唄,這樣調用者能夠傳一個參數過去告訴服務端「我想要一段調用XXX函數的js代碼,請你返回給我」,因而服務器就能夠按照客戶端的需求來生成js腳本並響應了。
這裏其實就是跨域的api接口。
看jsonp.html頁面的代碼:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 獲得航班信息查詢結果後的回調函數
var handleResponse = function(data){
alert(data.total);
};
// 提供jsonp服務的url地址(無論是什麼類型的地址,最終生成的返回值都是一段javascript代碼)
var url = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse";
// 建立script標籤,設置其屬性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script標籤加入head,此時調用開始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
這裏的API接口是豆瓣的一個獲取圖書信息的接口,本質就是在指定位置添加了一個script標籤,且是經過src方式,而後經過callback參數獲取返回值,返回值能夠直接使用,這樣就作到了跨域。
4.5 jQuery實現跨域
jQuery實現起來會更加簡單,由於它已經幫你包裝了一層,好比:指定url、數據類型,最重要的是,jQuery裏面,直接能夠經過success參數調用獲取的結果,固然,也可使用error設定錯誤提示。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "https://api.douban.com/v2/book/search?q=javascript&count=1",
dataType: "jsonp",
jsonp: "callback",//傳遞給請求處理程序或頁面的,用以得到jsonp回調函數名的參數名(通常默認爲:callback)
jsonpCallback:"flightHandler",//自定義的jsonp回調函數名稱,默認爲jQuery自動生成的隨機函數名,也能夠寫"?",jQuery會自動爲你處理數據
success: function(json){
alert(json.total);
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>
4.6 jsonp的總結
一、ajax和jsonp這兩種技術在調用方式上「看起來」很像,目的也同樣,都是請求一個url,而後把服務器返回的數據進行處理,所以jquery和ext等框架都把jsonp做爲ajax的一種形式進行了封裝;
二、但ajax和jsonp其實本質上是不一樣的東西。ajax的核心是經過XmlHttpRequest獲取非本頁內容,而jsonp的核心則是動態添加<script>標籤來調用服務器提供的js腳本。
三、因此說,其實ajax與jsonp的區別不在因而否跨域,ajax經過服務端代理同樣能夠實現跨域,jsonp自己也不排斥同域的數據的獲取。
四、還有就是,jsonp是一種方式或者說非強制性協議,如同ajax同樣,它也不必定非要用json格式來傳遞數據,若是你願意,字符串都行,只不過這樣不利於用jsonp提供公開服務。
總而言之,jsonp不是ajax的一個特例,哪怕jquery等巨頭把jsonp封裝進了ajax,也不能改變這一點!