上一篇文章 ,讲解了jQuery.ajax函数。这篇文章将其他一些细节补充完。下一篇文章则开始讲解,jQuery是如何将script动态载入、XMLHttpRequest、JSONP一起包装进jQuery.ajax里的。
jQuery.ajaxSetup
我们可以从主函数看出,参数是通过jQuery.ajaxSetup产生的:
//
通过jQuery.ajaxSetup改造参数对象
s =
jQuery.ajaxSetup( {}, options ),
那么jQuery.ajaxSetup在干些什么呢?
jQuery.ajaxSetup =
function
( target, settings ) {
//
如果有参数
return
settings ?
//
创建一个设置对象,先将jQuery.ajaxSettings的属性放进去,
//
然后将参数也放进去
ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
//
并将设置对象的属性放进jQuery.ajaxSettings对象里
ajaxExtend( jQuery.ajaxSettings, target );
};
ajaxExtend
ajaxExtend和jQuery.extend有一些不同,避免有些不需要深复制的属性进行深复制。
function
ajaxExtend( target, src ) {
var
key, deep,
flatOptions
= jQuery.ajaxSettings.flatOptions ||
{};
//
遍历src对象中的所有key
for
( key
in
src ) {
//
如果值不是undefined
if
( src[ key ] !==
undefined ) {
//
判断是不是不需要深复制的,如果不需要深复制,将属性直接写进target,
//
否则写进deep里存起来
//
我们可以从jQuery.ajaxSettings.flatOptions看到,
//
实际上不需要深复制的是url和context
( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] =
src[ key ];
}
}
//
如果deep不是undefined,证明需要深复制
if
( deep ) {
//
开始深复制
jQuery.extend(
true
, target, deep );
}
//
返回target
return
target;
}
ajaxHandleResponses
主体函数中response是通过ajaxHandleResponses来处理的:
//
得到响应数据
if
( responses ) {
//
通过ajaxHandleResponses处理数据
response =
ajaxHandleResponses( s, jqXHR, responses );
}
我们来看看该函数干了些什么。
function
ajaxHandleResponses( s, jqXHR, responses ) {
var
ct, type, finalDataType, firstDataType,
contents
=
s.contents,
dataTypes
=
s.dataTypes,
responseFields
=
s.responseFields;
//
将responseXXX填入jqXHR指定位置,也就是responseXML或者responseText
//
其中jqXHR.xml对应responseXML,jqXHR.text对应responseText
for
( type
in
responseFields ) {
if
( type
in
responses ) {
jqXHR[ responseFields[type] ]
=
responses[ type ];
}
}
//
删除掉通配dataType,得到返回的Content-Type
while
( dataTypes[ 0 ] === "*"
) {
dataTypes.shift();
if
( ct ===
undefined ) {
ct
= s.mimeType || jqXHR.getResponseHeader("Content-Type"
);
}
}
//
看看是不是我们能处理的Content-Type,比如图片这类二进制类型就不好处理了
if
( ct ) {
//
实际上能处理的就是text、xml和json
for
( type
in
contents ) {
if
( contents[ type ] &&
contents[ type ].test( ct ) ) {
//
如果是这三种类型,则推入dataTypes里
dataTypes.unshift( type );
break
;
}
}
}
//
如果dataTypes是我们想要的,也就是text、xml、json
if
( dataTypes[ 0 ]
in
responses ) {
//
则最终dataType就是这个了
finalDataType = dataTypes[ 0
];
//
否则
}
else
{
//
尝试转换成我们要的dataType
for
( type
in
responses ) {
//
如果dataTypes[ 0 ]不存在,则直接用type作为最终dataType
//
否则,看看能不能转换,能的话就用type作为最终dataType
if
( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0
] ] ) {
finalDataType
=
type;
break
;
}
//
保存第一个type
if
( !
firstDataType ) {
firstDataType
=
type;
}
}
//
用最终dataType或者用第一个type
finalDataType = finalDataType ||
firstDataType;
}
//
如果有最终dataType
if
( finalDataType ) {
//
如果最终dataType不是dataTypes[ 0 ]
if
( finalDataType !== dataTypes[ 0
] ) {
//
将finalDataType推入dataTypes队列里
dataTypes.unshift( finalDataType );
}
//
返回responses对应的finalDataType数据
return
responses[ finalDataType ];
}
}
jQuery.fn.load
实际上有两个jQuery.fn.load,一个是类似于onload的方法,另一个则是载入指定html页面。
前一个是jQuery.fn.on的简单扩展,而后面一个则是使用jQuery.ajax方法的扩展。
jQuery.fn.load =
function
( url, params, callback ) {
//
如果url不是string,且_load存在
//
证明这是onload方法,则调用保存的_load方法
if
(
typeof
url !== "string" &&
_load ) {
return
_load.apply(
this
, arguments );
}
var
selector, type, response,
self
=
this
,
off
= url.indexOf(" "
);
//
看看是不是载入指定元素,比如参数是'ajax/test.html #container'
if
( off >= 0
) {
//
分隔出需要载入的元素
selector =
url.slice( off, url.length );
//
分隔出真正的url
url = url.slice( 0
, off );
}
//
模拟重载
if
( jQuery.isFunction( params ) ) {
//
如果是函数那么就当这个是回调函数
callback =
params;
params
=
undefined;
//
如果参数是objects,那么定义type是POST
}
else
if
( params &&
typeof
params === "object"
) {
type
= "POST"
;
}
//
如果有需要修改的元素,开始请求
if
( self.length > 0
) {
jQuery.ajax({
url: url,
//
如果type为undefined,那么就会缺省为GET方法
type: type,
dataType:
"html"
,
data: params
//
完成后回调
}).done(
function
( responseText ) {
//
保存reponse
response =
arguments;
//
对元素写入html
//
如果selector存在
self.html( selector ?
//
先用一个div来存储整个html页面的DOM,在找到selector的相关html
jQuery("<div>"
).append( jQuery.parseHTML( responseText ) ).find( selector ) :
//
否则直接用responseText
responseText );
//
如果回调函数存在,则回调
}).complete( callback &&
function
( jqXHR, status ) {
self.each( callback, response
||
[ jqXHR.responseText, status, jqXHR ] );
});
}
return
this
;
};
jQuery.get & jQuery.post
这两个方法实际上就是通过jQuery.ajax扩展而来的。
//
加上get和post方法
jQuery.each( [ "get", "post" ],
function
( i, method ) {
//
jQuery.get或jQuery.post为
jQuery[ method ] =
function
( url, data, callback, type ) {
//
模拟重载
if
( jQuery.isFunction( data ) ) {
type
= type ||
callback;
callback
=
data;
data
=
undefined;
}
//
利用jQuery.ajax完成任务
return
jQuery.ajax({
url: url,
type: method,
dataType: type,
data: data,
success: callback
});
};
});
jQuery.getScript & jQuery.getJSON
jQuery.getScript和jQuery.getJSON则是由jQuery.get扩展而来的。
jQuery.getScript =
function
( url, callback ) {
return
jQuery.get( url, undefined, callback, "script"
);
};
jQuery.getJSON =
function
( url, data, callback ) {
return
jQuery.get( url, data, callback, "json"
);
}

