這篇文章跟大家介紹不用庫(框架)自己寫ajax,有興趣的朋友一起學習吧
#平常會使用ajax來請求數據,加載一個庫(框架),或許僅僅maybe就使用了它的ajax部分。
寫個ajax,一來可以經歷一下處理問題的過程,提陞技術能力,二來工作中有時真的用不著這麼大的一個庫(框架),用自己寫的,何樂不為呢。
先來看看流行的jQuery是怎樣呼叫ajax的
$.ajax({ url: 'test.php', //发送请求的URL字符串 type: 'GET', //发送方式 dataType: 'json', //预期服务器返回的数据类型 xml, html, text, json, jsonp, script data: 'k=v&k=v', //发送的数据 async: true, //异步请求 cache: false, //缓存 timeout: 5000, //超时时间 毫秒 beforeSend: function(){}, //请求之前 error: function(){}, //请求出错时 success: function(){}, //请求成功时 complete: function(){} //请求完成之后(不论成功或失败) });
這樣的呼叫是不是很舒適、方便,如果感覺舒適那自己動手寫也參照這種設計方式,不用太複雜,滿足所需就好。
先了解ajax的基礎知識
XMLHttpRequest 物件
XMLHttpRequest物件是ajax的核心,透過XMLHttpRequest物件來向伺服器發非同步請求,從伺服器發異步請求伺服器取得數據,所有現代瀏覽器(IE7 、Firefox、Chrome、Safari、Opera)均支援XMLHttpRequest 物件(IE5 和IE6 使用ActiveXObject)。
創建一個兼容的XMLHttpRequest對象
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
向伺服器發送請求
xhr.open(method,url,async);
//method:請求的類型;GET 或POST
//url:請求的URL
//async:true(非同步)或false(同步)
xhr.send(string);
//將請求傳送至伺服器
//string:僅用於POST請求
//GET 比POST 請求方式更簡單也更快,並且在大部分情況下都能用
//在以下情況中,請使用POST 請求:
//無法使用快取文件(更新伺服器上的檔案或資料庫)
//傳送大量資料到伺服器(POST 沒有資料量限制)
//傳送包含未知字元的使用者輸入時,POST 比GET 更穩定也更可靠
伺服器回應
使用XMLHttpRequest 物件的responseText 或responseXML 屬性來獲得來自伺服器的回應。
如果來自伺服器的回應是 XML,且需要作為 XML 物件進行解析,請使用 responseXML 屬性。
如果來自伺服器的回應並非 XML,請使用 responseText 屬性,responseText 屬性傳回字串形式的回應。
onreadystatechange 事件
# 當請求被傳送到伺服器時,我們需要執行一些基於回應的任務。每當 readyState 改變時,就會觸發 onreadystatechange 事件。 readyState 屬性存有 XMLHttpRequest 的狀態資訊。
XMLHttpRequest 物件的三個重要的屬性:
##onreadystatechange# //儲存函數(或函數名稱),每當readyState 屬性改變時,就會呼叫該函數
readyState //存有XMLHttpRequest 的狀態, 從0 到4 發生變化
0: 請求未初始化1: 伺服器連線已建立
2: 請求已接收
3: 請求處理中
4: 請求已完成,且回應已就緒
status //200: "OK", 404: 未找到頁面
在onreadystatechange 事件中,我們規定當伺服器回應已做好處理的準備時所執行的任務, 當readyState等於4 且status為200 時,表示響應已就緒。xhr.onreadystatechange = function(){ if( xhr.readyState == 4 && xhr.status == 200 ){ //准备就绪 可以处理返回的 xhr.responseText 或者 xhr.responseXML } };
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); xhr.onreadystatechange = function(){ if( xhr.readyState == 4 && xhr.status == 200 ){ //准备就绪 可以处理返回的 xhr.responseText 或者 xhr.responseXML } }; xhr.open(method,url,async); xhr.send(string);
url += (url.indexOf('?') < 0 ? '?' : '&') + '_='+ (+new Date()); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
開始寫自己的ajax
先寫一個基本的,定義好各種參數選項,供參考var $ = (function(){ //辅助函数 序列化参数 function param(data){ //.. } function ajax(opts){ var _opts = { url : '/', //发送请求URL地址 type : 'GET', //发送请求的方式 GET(默认), POST dataType : '', //预期服务器返回的数据类型 xml, html, text, json, jsonp, script data : null, //发送的数据 'key=value&key=value', {key:value,key:value} async : true, //异步请求 ture(默认异步), false cache : true, //缓存 ture(默认缓存), false timeout : 5, //超时时间 默认5秒 load : function(){}, //请求加载中 error : function(){}, //请求出错时 success : function(){}, //请求成功时 complete : function(){} //请求完成之后(不论成功或失败) }, aborted = false, key, xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); for(key in opts) _opts[key] = opts[key]; /* if(_opts.dataType.toLowerCase() === 'script'){ //.. } if(_opts.dataType.toLowerCase() === 'jsonp'){ //.. } */ if(_opts.type.toUpperCase() === 'GET'){ if(param(_opts.data) !== ''){ _opts.url += (_opts.url.indexOf('?') < 0 ? '?' : '&') + param(_opts.data); } !_opts.cache && ( _opts.url += (_opts.url.indexOf('?') < 0 ? '?' : '&') + '_='+(+new Date()) ); } function checkTimeout(){ if(xhr.readyState !== 4){ aborted = true; xhr.abort(); } } setTimeout(checkTimeout, _opts.timeout*1000); xhr.onreadystatechange = function(){ if( xhr.readyState !== 4 ) _opts.load && _opts.load(xhr); if( xhr.readyState === 4 ){ var s = xhr.status, xhrdata; if( !aborted && ((s >= 200 && s < 300) || s === 304) ){ switch(_opts.dataType.toLowerCase()){ case 'xml': xhrdata = xhr.responseXML; break; case 'json': xhrdata = window.JSON && window.JSON.parse ? JSON.parse(xhr.responseText) : eval('(' + xhr.responseText + ')'); break; default: xhrdata = xhr.responseText; } _opts.success && _opts.success(xhrdata,xhr); }else{ _opts.error && _opts.error(xhr); } _opts.complete && _opts.complete(xhr); } }; xhr.open(_opts.type,_opts.url,_opts.async); if(_opts.type.toUpperCase() === 'POST'){ xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); } xhr.send(_opts.type.toUpperCase() === 'GET' ? null : param(_opts.data)); } return { ajax: ajax } })();定義好了參數選項,來分析一下。其中 dataType 是整個ajax的重點,程式碼的簡單或複雜都在它了。 在這裡dataType為預期伺服器傳回的資料類型:xml, html, text, json, jsonp, script 1. 為xml時,來自伺服器的回應是XML,使用responseXML 屬性取得傳回的資料 2. 為html、text、json時,使用responseText 屬性取得傳回的資料
a. 为html时,返回纯文本HTML信息,其中包含的script标签是否要在插入dom时执行 ( 代码复杂度+3 )
b. 为json时, 返回JSON数据,要安全、要便捷、要兼容 ( 代码复杂度+2 )
3. 为jsonp时,一般跨域才用它,不用原来的ajax请求了,用创建script法( 代码复杂度+2 )
4. 为script时: 要跨域时,不用原来的ajax请求了,用创建script法( 代码复杂度+1 ); 不跨域,返回纯文本JavaScript代码, 使用 responseText 属性获取返回的数据 ( 代码复杂度+1 )
其中,在html片段中的script标签、jsonp、script,都要用到创建script标签的方式。
处理dataType为json
xhrdata = window.JSON && window.JSON.parse ? JSON.parse(xhr.responseText) : eval('(' + xhr.responseText + ')');
这是最简单的处理方式了,要JSON兼容,可以用json2.js。
处理dataType为jsonp
jsonp是要通过script标签来请求跨域的,先了解下流程:
这上图中 a.html中请求了 http://www.b.com/b.php?callback=add (在ajax程序中请求url就是这个链接),在b.php中读取了传过来的参数 callback=add 根据获取到的参数值(值为add),以JS语法生成了函数名,并把json数据作为参数传入了这个函数,返回以JS语法生成的文档给a.html,a.html解析并执行返回的JS文档,调用了定义好的add函数。
在程序中一般采用更通用的方式去调用,比如下面这个广泛使用的loadJS函数:
function loadJS(url, callback) { var doc = document, script = doc.createElement('script'), body = doc.getElementsByTagName('body')[0]; script.type = 'text/javascript'; if (script.readyState) { script.onreadystatechange = function() { if (script.readyState == 'loaded' || script.readyState == 'complete') { script.onreadystatechange = null; callback && callback(); } }; } else { script.onload = function() { callback && callback(); }; } script.src = url; body.appendChild(script); }
这样把请求的url,传入loadJS函数,得到一样的结果。
loadJS('http://www.b.com/b.php?callback=add');
因为是动态创建script,请求成功返回,JS代码就立即执行,如果请求失败是没有任何提示的。因此自定义的参数选项: _opts.success 能调用,_opts.error不能调用。
ajax处理jsonp也有两种情况:
1. 设置了请求URL后的参数 callback=add 特别是定义了函数名add,请求成功返回,JS代码就立即执行(这里就是调用 add({"a":8,"b":2}) )
2. 在_opts.success中处理JSON数据,就是请求成功返回,JS代码不执行,并把函数中的参数挪出来,作为_opts.success的参数返回( 这里相当于处理字符串 'add({"a":8,"b":2})' ,去掉 'add(' 和 ‘)',得到 {"a":8,"b":2} )
处理dataType为html
如果不处理HTML片段中script标签,直接把responseText返回值插入DOM树就可以了。如果要处理script,就要把HTML片段中的script标签找出来,对买个script单独处理,并注意是script标签中包含的JS代码还是通过src请求的。
处理dataType为script
如果要跨域时,用创建script的方式,和处理jsonp类似; 不跨域,使用 responseText 属性获取返回的数据,可以用 eval 来让代码执行,也可以创建script来执行。
function addJS(text) { var doc = document, script = doc.createElement('script'), head = doc.getElementsByTagName('body')[0]; script.type = 'text/javascript'; script.text = text; body.appendChild(script); }
到此ajax差不多分析完了,根据实际需要,添加各种功能,去思考每种功能是怎样实现的,并能找到解决方法。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
初步了解JavaScript,Ajax,jQuery,并比较三者关系
以上是簡單介紹不用函式庫(框架)自己寫ajax的詳細內容。更多資訊請關注PHP中文網其他相關文章!