Q:AJAX以何種格式來交換數據?跨域的需求如何解決?javascript
A:用JSON來傳數據,靠JSONP來跨域(具體參見下文)php
AJAX = Asynchronous(英[eɪˈsɪŋkrənəs]) JavaScript and XML(異步的 JavaScript 和 XML)。java
XMLHttpRequest 用於在後臺與服務器交換數據。這意味着能夠在不從新加載整個網頁的狀況下,對網頁的某部分進行更新。node
全部現代瀏覽器均支持 XMLHttpRequest 對象(IE5 和 IE6 使用 ActiveXObject)。jquery
// 建立 XMLHttpRequest 對象 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"); } // 向服務器發送請求 // 當使用 async=true 時,請規定在響應處於 onreadystatechange 事件中的就緒狀態時執行的函數 // async=false 時,請不要編寫 onreadystatechange 函數 - 把代碼放到 send() 語句後面便可 xmlhttp.onreadystatechange=function(){ if (xmlhttp.readyState==4 && xmlhttp.status==200){ // 來自服務器的響應 responseText:字符串形式 responseXML:XML形式 document.getElementById("myDiv").innerHTML=xmlhttp.responseText; } } xmlhttp.open("GET","test1.txt",true); xmlhttp.send();
open(method,url,async)web
method:請求的類型;GET 或 POST url:文件在服務器上的地址(該文件能夠是任何類型的文件或服務器腳本文件) async:true(異步)或 false(同步)
send(string)ajax
string:僅用於 POST 請求
與 POST 相比,GET 更簡單也更快,而且在大部分狀況下都能用。
然而,在如下狀況中,請使用 POST 請求:
沒法使用緩存文件(更新服務器上的文件或數據庫)
向服務器發送大量數據(POST 沒有數據量限制)
發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠數據庫
避省得到的是緩存的結果,向URL添加一個惟一的 IDjson
xmlhttp.open("GET","demo_get.asp?t=" + Math.random(),true);
但願經過 GET 方法發送信息,請向 URL 添加信息跨域
xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates",true);
須要像 HTML 表單那樣 POST 數據,請使用 setRequestHeader() 來添加 HTTP 頭。而後在 send() 方法中規定您但願發送的數據
// 向請求添加 HTTP 頭。 // setRequestHeader(header,value) // header: 規定頭的名稱 value: 規定頭的值 xmlhttp.open("POST","ajax_test.asp",true); xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xmlhttp.send("fname=Bill&lname=Gates");
XMLHttpRequest 對象的 responseText 或 responseXML 屬性
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
// 請求 books.xml 文件,並解析響應 xmlDoc=xmlhttp.responseXML; txt=""; x=xmlDoc.getElementsByTagName("ARTIST"); for (i=0;i<x.length;i++) { txt=txt + x[i].childNodes[0].nodeValue + "<br />"; } document.getElementById("myDiv").innerHTML=txt;
當請求被髮送到服務器時,咱們須要執行一些基於響應的任務。
readyState 屬性存有 XMLHttpRequest 的狀態信息。
每當 readyState 改變時,就會觸發 onreadystatechange 事件。
onreadystatechange
存儲函數(或函數名),每當 readyState 屬性改變時,就會調用該函數。
readyState
存有 XMLHttpRequest 的狀態。從0到4發生變化。(一共被觸發 5 次) 0: 請求未初始化 1: 服務器鏈接已創建 2: 請求已接收 3: 請求處理中 4: 請求已完成,且響應已就緒
status
200: "OK" 404: 未找到頁面
callback 函數是一種以參數形式傳遞給另外一個函數的函數
JavaScript 對象表示法(JavaScript Object Notation)
是存儲和交換文本信息的語法。相似 XML,比XML更小、更快,更易解析。
JSON有六種類型的值:對象,數組,字符串,數字,布爾值和特殊值null。
數據在名稱/值對中
數據由逗號分隔
花括號保存對象
方括號保存數組
對象結構以」{」大括號開始,以」}」大括號結束。中間部分由0或多個以」,」分隔的」key(關鍵字)/value(值)」對構成,關鍵字字符串和值之間以」:」分隔
{ key1:value1, key2:value2, ... }
數組結構以」[」開始,」]」結束。中間由0或多個以」,」分隔的值列表組成
[ { key1:value1, key2:value2, ... }, { key1:value1, key2:value2, ... }, ]
JSON對象(ECMAScript 5中添加的, 早期JSON解析基本都使用javascript的eval()函數。可是eval有一些性能和安全上的缺點,ECMAScript對解析JSON對象進 行了規範,定義了全局對象JSON,支持的瀏覽器有標準瀏覽器和IE8+。對於不支持的瀏覽器能夠引入json2.js文件。)有stringify與parse這兩個方法。
將javascript對象序列化爲JSON格式的字符串
JSON.stringify(ob,filter,indent)包含三個參數,一般咱們在使用的時候只帶第一個參數,來返回字符串。
ob:要轉化成JSON字符串的對象,數組,原始值。
filter:是一個可選的參數,一般是一個函數,用來在字符串化前對值作一些替換。也能夠是一個數組,包含哪些須要字符串化的屬性名。就是用來過濾的。
// 第二個參數是數組過濾器 var oJson = { name: 'hum', age: 20, sex: 1}; console.log(JSON.stringify(oJson, ['age', 'sex'])); // {"age":20,"sex":1} // 第二個參數是函數過濾器 // 若是該參數是函數,則它是一個替換函數,該函數會在每個須要字符串化的對象上調用。 // 這個函數的第一個參數是該對象中的屬性名或數組的序號,第二個則是值自己。 // 函數的返回值會替換掉須要字符串化的值,若是函數返回undefined或沒有任何的返回值,則會在字符串化的時候忽略這個值。 var oJson = { name: 'hum', age: 26, sex: 1, love: ['swing', 'jump']}; console.log(JSON.stringify(oJson, function(k, v){ switch (k){ case 'age': return v > 20 ? '成年': '未成年'; case 'love': return v.join(','); case 'sex': return undefined; default : return v; } })); // {"name":"hum","age":"成年","love":"swing,jump"}
indent:也是一個可選參數,在須要輸出格式化的可閱讀的代碼時,使用indent參數來指定用來縮進的字符串或空格。若是省略該參數,返回的字符串將不帶任何的額外的空格,這樣輸出的值很難閱讀。就是用來格式化的。
JSON.parse用來解析json格式的字符串(返回一個對象,數組或原始值)
JSON.parse(s,reviver)包含兩個參數
s:要解析的字符串
reviver:用來轉換解析值得可選函數
一般使用只使用第一個參數,可選參數reviver,主要是在返回解析值以前,對其進行過濾或後期處理。
reviver函數會在從s中解析的每一個原始值調用一次。
調用reviver函數是帶有兩個參數,第一個屬性名(對象的屬性名或是轉換成字符串的數組序號),第二個參數是對象的屬性或是數組的元素值。
reviver函數會做爲包含原始值的對象/數組的方法來調用。
reviver函數的返回值會成爲屬性的新值,若是reviver返回第二個參數,則屬性不變。
若是reviver返回undefined或不凡會任何值,則會從對象或是數組中刪除屬性。
var oJson = { name: 'hum', age: 26, sex: 1, love: ['swing', 'jump'], birthday: '1988-01-12'}; var sJson = JSON.stringify(oJson); console.log(sJson); //{"name":"hum","age":26,"sex":1,"love":["swing","jump"],"birthday":"1988-01-12"} console.log(JSON.parse(sJson)); console.log(JSON.parse(sJson, function (k, v) { if(k == 'birthday'){ // 返回日期對象 return new Date(v); }else if(k == 'sex'){ // sex不在了 return undefined; }else{ return v; } }));
http://www.runoob.com/jsontool
Jsonp(JSON with Padding) 是 json 的一種"使用模式",可讓網頁從別的域名(網站)那獲取資料,即跨域讀取數據。
一、衆所周知,Ajax直接請求普通文件存在跨域無權限訪問的問題(緣由參見 同源策略-web腳本安全)
二、可是,HTML的<script>標籤是例外,能夠突破同源策略從其餘來源獲取數據(實質是擁有"src"這個屬性的標籤都擁有跨域的能力,好比<script>、<img>、<iframe>)
三、因而能夠判斷,當前階段若是想經過純web端(ActiveX控件、服務端代理、屬於將來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件裏,供客戶端調用和進一步處理(如今可使用nodejs作中間件了,本文暫且不表,改天我詳細寫一下~);
首先在客戶端註冊一個callback, 而後把callback的名字傳給服務器。
此時,服務器先生成 json 數據。
而後以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 jsonp.
最後將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
客戶端瀏覽器,解析script標籤,並執行返回的 javascript 文檔,此時數據做爲參數,傳入到了客戶端預先定義好的 callback 函數裏.(動態執行回調函數)
// 原生js 添加<script>標籤的方法 //(函數名可約定,或經過地址參數傳遞) function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function(){ //將自定義的回調函數名result傳入callback參數中 addScriptTag("localhost/bns-relation/index.php?r=BnsRelation/BnsOfProd&callback=result"); } //自定義的回調函數result function result(data) { //咱們就簡單的獲取數據 console.log(data); }
// zepto,jquery的JSONP用法 var qsData = {'searchWord':$("#searchWord").attr("value"),'currentUserId': $("#currentUserId").attr("value"),'conditionBean.pageSize':$("#pageSize").attr("value")}; $.ajax({ async:false, url: http://跨域的dns/document!searchJSONResult.action, type: "GET", dataType: 'jsonp', jsonp: 'jsoncallback', data: qsData, timeout: 5000, beforeSend: function(){ //jsonp 方式此方法不被觸發.緣由多是dataType若是指定爲jsonp的話,就已經不是ajax事件了 }, success: function (json) {//客戶端jquery預先定義好的callback函數,成功獲取跨域服務器上的json數據後,會動態執行這個callback函數 if(json.actionErrors.length!=0){ alert(json.actionErrors); } genDynamicContent(qsData,type,json); }, complete: function(XMLHttpRequest, textStatus){ $.unblockUI({ fadeOut: 10 }); }, error: function(xhr){ //jsonp 方式此方法不被觸發.緣由多是dataType若是指定爲jsonp的話,就已經不是ajax事件了 //請求出錯處理 alert("請求出錯(請檢查相關度網絡情況.)"); } });
不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;
兼容性更好,在更加古老的瀏覽器中均可以運行,不須要XMLHttpRequest或ActiveX的支持;
在請求完畢後能夠經過調用callback的方式回傳結果。
只支持GET請求而不支持POST等其它類型的HTTP請求;
只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JavaScript調用的問題。
ajax和jsonp其實本質上是不一樣的東西
ajax的核心是經過XmlHttpRequest獲取非本頁內容
而jsonp的核心則是動態添加<script>標籤來調用服務器提供的js腳本
JSON(JavaScript Object Notation)和JSONP(JSON with Padding)雖然只一個字母差異,但其實根本不是一回事兒JSON是一種數據交換格式而JSONP是一種非官方跨域數據交互協議