好,我們接著上篇的內容接續來講解Ajax相關的內容。今天要將的是我們自己模仿著jQuery封裝Ajax請求。
原生的Ajax請求上篇文章已經都說清楚了,大家應該會感覺調用起來代碼寫的多,很多細節可能都記不住,一旦有了這個感覺之后,我們就可以來考慮一下將原生的Ajax請求封裝在一個方法中。例如:
functionmyAjax() {
//在這里寫XMLHttpRequest的代碼,最后將成功之后的數據回調}
既然要封裝到一個方法中,那我們就需要將一些會變化的東西拿出來,通過參數的方式進行傳遞,也就是myAjax方法的定義中需要有參數,那么參數有多少個呢,又分別是什么呢?
首先,url肯定是會變的,所以url是一個參數,請求方式是get還是post也是不確定的,如果是post請求的話,那么請求參數也是不確定的,還有同步異步也最好讓調用者來確定。最后,請求的數據是json呢還是xml也是不確定的。
通過上訴分析,我們可以得出下面代碼:
//callback是傳遞進來的回調函數
functionmyAjax(url,type,param,dataType,async,callback){
//兼容處理varxhr=null;
if(window.XMLHttpRequest){
xhr=newXMLHttpRequest();
}else{
xhr=newActiveXObject('Microsoft.XMLHTTP');
}
//如果是get請求,則需要將參數跟在url后面if(type =='get'){
url +="?"+ param;
}
xhr.open(type,url,async);
vardata=null;
//如果是post請求,則需要在send方法中將參數放進去,并且需要設置請求頭if(type =='post'){
data= param;
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
xhr.send(data);
//如果是異步的話,則需要監聽xhr的onreadystatechange的事件,否則就不需要監聽if(async) {
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
vardata=xhr.responseText;
//如果是json數據的話,將數據轉化成js中的json類型的對象,這樣會方便后續解析if(dataType =='json'){
data=JSON.parse(data);
}
callback(data);
}
}
}
}else{
if(xhr.readyState==4){
if(xhr.status==200){
vardata=xhr.responseText;
if(dataType =='json'){
data=JSON.parse(data);
}
callback(data);
}
}
}
}
上面的代碼就是我們自己對原生的Ajax進行的封裝。調用的代碼如下:
<scripttype="text/javascript">
window.onload=function(){
varbtn=document.getElementById('btn');
btn.onclick =function(){
varuname=document.getElementById('username').value;
varpw=document.getElementById('password').value;
myAjax('./01check.php',
'get',
'username='+uname+'&password='+pw,
'json',
true,
new function(data){console.log(data);})
}
}
script>
這是最容易想到的封裝方法。不過有瑕疵。為什么呢,因為調用起來不方便。在定義myAjax方法的時候,設置了6個參數,也就是每次我調用myAjax方法的時候,我都需要傳遞6個參數,一個都不能少,并且參數的順序還不能錯。這就是調用起來不方便的地方。因此我們需要優化。我們可以參考jQuery對Ajax的封裝,然后將myAjax進行修改。
在jQuery中使用Ajax很方便,代碼如下:
<scripttype="text/javascript">
window.onload=function(){
varbtn=document.getElementById('btn');
btn.onclick =function(){
varuname=document.getElementById('username').value;
varpw=document.getElementById('password').value;
$.ajax({
type:'get',
url:'./01check.php',
data:{username:uname,password:pw},
dataType:'json',
success:function(data){
}
});
}
}
script>
這就是jQuery中的Ajax調用。它有什么特點呢?type、url等之間的順序可以任意,type可以不寫,默認就是get,這就比我們剛才的方法調用要簡單很多。那么它是怎么來實現的呢?仔細觀察我們可以發現,在$.ajax()方法調用中,參數傳遞的其實是一個對象{},對象中都是以鍵值對的方式存在。這就給我們一個啟發,參數傳遞可以以對象的方式傳遞,這樣就可以不用考慮參數順序的問題。并且我們還可以很方便的加上默認值。那接下來我們就仿照jQuery的方法將myAjax給一步步的改善。
functionmyAjax(obj){
//我們可以自己定義一些默認值,比如get請求就可以成為默認值vardefaults= {
type:'get',//默認的請求方式為getdata: {},//請求的參數也可以用對象的方式進行維護,這樣會方便很多url:'#',
dataType:'text',
async:true,
success:function(data){console.log(data)}
}
}
defaults就是默認值,obj就是傳遞過來的值,如果obj沒有傳遞某些值的話,那么就使用defaults中定義的值,如果obj傳遞了一些值過來,那么就需要使用obj中的值,所以下一步,就是要將obj的值覆蓋defaults中的值,代碼如下:
functionmyAjax(obj){
//我們可以自己定義一些默認值,比如get請求就可以成為默認值vardefaults= {
type:'get',//默認的請求方式為getdata: {},//請求的參數也可以用對象的方式進行維護,這樣會方便很多url:'#',
dataType:'text',
async:true,
success:function(data){console.log(data)}
}
for(varkeyinobj){
defaults[key] = obj[key];//用obj中的值覆蓋defaults中的值
}
}
這步做完之后,接下來就很簡單了,將之前myAjax方法中,使用參數的地方,都變成使用defaults中的值就可以了,完整代碼如下:
functionmyAjax(obj){
//我們可以自己定義一些默認值,比如get請求就可以成為默認值vardefaults= {
type:'get',//默認的請求方式為getdata: {},//請求的參數也可以用對象的方式進行維護,這樣會方便很多url:'#',
dataType:'text',
async:true,
success:function(data){console.log(data)}
}
for(varkeyinobj){
defaults[key] = obj[key];//用obj中的值覆蓋defaults中的值}
// 1、創建XMLHttpRequest對象varxhr=null;
if(window.XMLHttpRequest){
xhr=newXMLHttpRequest();
}else{
xhr=newActiveXObject('Microsoft.XMLHTTP');
}
// 把對象形式的參數轉化為字符串形式的參數/*如:{username:'zhangsan','password':123}轉換為username=zhangsan&password=123*/varparam='';
for(varattrinobj.data){
param+=attr+'='+ obj.data[attr] +'&';
}
if(param){
param=param.substring(0,param.length-1);
}
// 處理get請求參數并且處理中文亂碼問題if(defaults.type=='get'){
defaults.url+='?'+encodeURI(param);
}
// 2、準備發送(設置發送的參數)xhr.open(defaults.type,defaults.url,defaults.async);
// 處理post請求參數并且設置請求頭信息(必須設置)vardata=null;
if(defaults.type=='post'){
data=param;
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
// 3、執行發送動作xhr.send(data);
// 處理同步請求,不會調用回調函數if(!defaults.async){
if(defaults.dataType=='json'){
returnJSON.parse(xhr.responseText);
}else{
returnxhr.responseText;
}
}
// 4、指定回調函數(處理服務器響應數據)xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
vardata=xhr.responseText;
if(defaults.dataType=='json'){
// data = eval("("+ data +")");data=JSON.parse(data);
}
defaults.success(data);
}
}
}
}
好,現在我們就模仿了jQuery封裝了自己的myAjax方法,順著我們的封裝思路有以下幾個歷程:
1、簡單封裝,需要參數的話定義在方法的括號中
2、為了方法參數傳遞時候順序可以隨意,因此想到了以對象的方式傳遞參數。
3、方法中并不是每一個參數都需要傳遞,我們可以設置默認值,然后將傳遞過來的值覆蓋默認值
那jQuery中Ajax代碼就是這樣寫的嗎?其實還有點差別,這里就涉及到跨域的問題,我們下一篇文章再來說明一下。