今天決定學習一下Ajax異步的XMLHttpRequest對象,平時一直使用jQuery.ajax()就萬事大吉,javascript
當本身要實現一套時才發現當中的細節事情!jQuery源碼真的博大精深優美得很;php
先從w3cschool看一下基本的使用方式,參考的jQ版本是v1.11.1html
http://www.w3school.com.cn/xml/xml_http.asp java
基本流程是先作簡單XMLHttpRequest兼容處理,提交請求,最後是回調處理結果;
node
setup1 配置ajax
開始時候在想怎樣才能寫出優美的參數傳值,看jQ源碼發現是使用jQuery.extend,並且這函數在不少地方都在應用,看來份量很重噢;json
手冊介紹是用一個或多個其餘對象來擴展一個對象,返回被擴展的對象;若是不指定target,則給jQuery命名空間自己進行擴展。跨域
jQ是先定義了基本參數對象ajaxSettings#8830行開始;而後調用ajaxSetup方法,其實這貨仍是調用了jQuery.extend去合併對象;只是判斷是不是擴展配置對象;瀏覽器
本身太賴了只作最簡參數單合併和獲取回調方法事情;服務器
function ajaxSetup(opations) { if (typeof opations == 'object') { for (key in opations) { //Code.... } } return ajaxSetting; }
setup2
實例化XMLHttpRequest就交由兩個方法isWindowXHR和isIEXHR,而後由JS自行判斷使用哪個;
這裏基本沒什麼特別!jQuery基本也是這麼幹的!只是它還作了不少IE6~9的瀏覽器兼容代碼(難關jQ2就放棄治療它們)
// Create the request object // (This is still attached to ajaxSettings for backward compatibility) jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ? // Support: IE6+ function() { // XHR cannot access local files, always use ActiveX for that case return !this.isLocal && // Support: IE7-8 // oldIE XHR does not support non-RFC2616 methods (#13240) // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9 // Although this check for six methods instead of eight // since IE also does not support "trace" and "connect" /^(get|post|head|put|delete|options)$/i.test( this.type ) && createStandardXHR() || createActiveXHR(); } : // For all other browsers, use the standard XMLHttpRequest object createStandardXHR;
我萬惡地幾行沒營養的代碼就行了!
var xmlHttp = isWindowXHR() || isIEXHR(); function isWindowXHR() { //Code.... } function isIEXHR() { //Code.... }
setup3 傳值請求服務器和處理回調
這裏jQ作了不少參數值的過濾、是不是跨域請求、head部分組裝,是否跨域分開了好像是兩部分處理(不知道有沒有看錯!代碼太長了)
搜源碼jQuery.ajaxTransport能夠找到;
而後也是跟XMLHttpRequest流程定義調用send處理onreadystatechange在不一樣狀態觸發事件;
//TODO:增長其餘狀態處理 function stateChange() { if (xmlHttp.readyState == 4) { //Code.... } } return { 'ajax' : function(opations) { var settings = ajaxSetup(opations); if (xmlHttp !== null && settings) { xmlHttp.onreadystatechange = stateChange; switch(settings['type'].toUpperCase()) { case 'POST': //Code.... break; case 'GET': //Code.... break; } } else { alert("Your browser does not support XMLHTTP."); } } };
在此次學習中發現一個很好的網站
whatwg.org
後來發現這傢伙跟W3C是頗有冤緣;
詳細看這裏《哪一個HTML5?WHATWG與W3C或分道揚鑣》
http://www.cnblogs.com/xesam/archive/2012/07/23/2604254.html
完整代碼:
index.html
<DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript" src="xhr.js"></script> </head> <body> <input type="button" id="gTime" value="獲取服務器時間" /> <div id="serTime">00:00:00</div> </body> </html> <script type="text/javascript"> gTime.addEventListener("click", function(){ $.ajax({ type: "POST", url: "xmlHttpRequestAction.php", dataType : 'json', async : true, data: "name=John&location=Boston", success : function(msg) { var obj = eval('(' + msg + ')'); serTime.childNodes[0].nodeValue = obj.date; console.log(obj); } }); }, false); </script>
xhr.js
var $ = (function(Global){ var xmlHttp = isWindowXHR() || isIEXHR(); var callback = {}; var ajaxSetting = { //TODO:過濾地址符號,例如結尾的"/" 'url' : location.href, 'type' : 'GET', //TODO:增長類型轉換判斷 'dataType' : 'text', 'async' : true, //TODO:增長支持對象類型 'data' : null }; function isWindowXHR() { try { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } } catch (e) {} } function isIEXHR() { try { if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } } catch (e) {} } function ajaxSetup(opations) { if (typeof opations == 'object') { for (key in opations) { if (typeof ajaxSetting[key] !== 'undefined') { ajaxSetting[key] = opations[key]; } else { switch(typeof opations[key]) { case 'function': callback[key] = opations[key]; break; } } } } return ajaxSetting; } //TODO:增長其餘狀態處理 function stateChange() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { if (callback.success) { //Success return callback.success(xmlHttp.responseText); } else { return xmlHttp.response; } } else { alert("Problem retrieving XML data"); } } } /* https://xhr.spec.whatwg.org/ */ return { 'ajax' : function(opations) { var settings = ajaxSetup(opations); if (xmlHttp !== null && settings) { xmlHttp.onreadystatechange = stateChange; switch(settings['type'].toUpperCase()) { case 'POST': xmlHttp.open('POST', settings['url'], settings['async']); xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"); xmlHttp.send(ajaxSetting['data']); break; case 'GET': settings['url'] += ('?' + ajaxSetting['data']); xmlHttp.open('GET', settings['url'], settings['async']); xmlHttp.send(null); break; } } else { alert("Your browser does not support XMLHTTP."); } } }; })(window);
xmlHttpRequestAction.php
<?php date_default_timezone_set("PRC"); echo json_encode(array('date'=>date('Y-m-d h:i:s'),'POST'=>$_POST,'GET'=>$_GET, 'content'=>'中文')); ?>