以下的内容只是个人的理解,技术有限,如有问题请指正(看得jq版本是1.3.2)
jQuery的ajax, 就是我看的和理解,可以用在3个方面,一个是取一个script地址并执行一些操作 $jQuery.getScript; 一个是jsonp $jQuery.getJSON;还有一个就是一般的ajax应用了我主要记录的是jsonp 和 ajax 这方面的个人理解..
jsonp
我的理解是:
创建一个全局的回调函数(假如是handler)
在创建一个<script>标签,去请求一个服务器端的地址(假如是http://www.xxx.com, 写在script标签里面就是 http://www.xxx.com?callback=handler callback是跟别人约定好的,也可以不要callback 别人主要是通过这个约定好的callback取到 函数名 handler 然后返回一个可以执行的js)
服务器端返回一个可以执行的js代码 (假如是 handler({name : "hello world"}))
一个简单的例子
上面的handler是 gg函数
请求的地址是 http://active.zol.com.cn/guofeng/profile2.php?callback=gg
请求的地址是 http://active.zol.com.cn/guofeng/profile2.php?callback=gg
截图为证
返回的是
页面上多了一段可以执行的script
jQuery里面 有个默认配置
ajaxSettings: {
//url: location.href,
global : true,
type : "GET",
contentType : "application/x-www-form-urlencoded",
processData : true,
async : true,
/*
timeout: 0,
data: null,
username: null,
password: null,
*/
// Create the request object; Microsoft failed to properly
// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
// This function can be overriden by calling jQuery.ajaxSetup
xhr:function(){
return window.ActiveXObject
? new ActiveXObject("Microsoft.XMLHTTP")
: new XMLHttpRequest();
},
accepts: {
xml: "application/xml, text/xml",
html: "text/html",
script: "text/javascript, application/javascript",
json: "application/json, text/javascript",
text: "text/plain",
_default: "*/*"
}
}
//url: location.href,
global : true,
type : "GET",
contentType : "application/x-www-form-urlencoded",
processData : true,
async : true,
/*
timeout: 0,
data: null,
username: null,
password: null,
*/
// Create the request object; Microsoft failed to properly
// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
// This function can be overriden by calling jQuery.ajaxSetup
xhr:function(){
return window.ActiveXObject
? new ActiveXObject("Microsoft.XMLHTTP")
: new XMLHttpRequest();
},
accepts: {
xml: "application/xml, text/xml",
html: "text/html",
script: "text/javascript, application/javascript",
json: "application/json, text/javascript",
text: "text/plain",
_default: "*/*"
}
}
accepts 是设置请求头 accepts里面的配置项
type 是提交类型
async 是 是否异步 true 表示异步
processData 是否修改data的结构 如果是true 表示修改
ifModified 如果设置了这一项 就要设置http请求头里面的 If-Modified-Since
contentType 设置请求头contentType的类型
application/xml;
application/x-www-form-urlencoded
application/json
application/xml;
参数传递用<xml>
截图为证
application/x-www-form-urlencoded
参数传递用就是一般的字符串
截图为证参数传递用就是一般的字符串
application/json
参数传递是json形式的(cnblogs就是这样的形式)
参数传递是json形式的(cnblogs就是这样的形式)
截图为证
jquery.ajax的前部分主要是对jsonp 和 创建script 的处理
jq的jsonp的用法是 callback=? 要以这种形式
所以前面部分就是判断url 是不是这中形式 不是这中形式就转成这种形式
同时创建一个全局的变量当函数 回掉的时候执行该函数
View Code
//extend 的第一个参数为true 表示深度复制
//创建一个新的对象 jq.ajaxSettings全部copy过去 把s复制过去
s = jq.extend(true, s, jq.extend(true, {}, jq.ajaxSettings, s));
var jsonp,
// jsonp 的回调函数名字要以这种方式才行
jsre = /=\?(&|$)/g,
status,
data,
type = s.type.toUpperCase();
//如果data不是字符串 转成字符串
if ( s.data && typeof s.data !== "string" )
s.data = jq.param(s.data);
if ( s.dataType == "jsonp" ) {
if ( type == "GET" ) {
if ( !s.url.match(jsre) ){
//get 方式 参数都在url的后面
//如果没有=?这种形式 就转成这种形式 这是jq的jsonp形式 后面要把?变成函数名
//转成这种形式 http://www.xxx.com?callback=?
s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
}//http://www.baidu.com?callback=?
} else if ( !s.data || !s.data.match(jsre) ){
//post方式 有专为存放参数的地方 这里是把参数和回调都转一下
//形式 xx=xx&oo=oo.......&callback=?
s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
}
s.dataType = "json";
}
// url 符合 定义的jsonp形式 或者 s.data符合jsonp形式
if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
// 这里的jsonp 就是后面的可执行函数的 函数名了
jsonp = "jsonp" + jsc++;
// Replace the =? sequence both in the query string and the data
// /=\?(&|$)/g
//将 ? 转 成函数名字
if ( s.data )
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
s.url = s.url.replace(jsre, "=" + jsonp + "$1");
s.dataType = "script";
// 定义全局的函数名了 后面请求完毕后就会执行这个函数
window[ jsonp ] = function(tmp){
data = tmp;
success();
//complete();
// Garbage collect
window[ jsonp ] = undefined;
try{ delete window[ jsonp ]; } catch(e){}
if ( head )
head.removeChild( script );
};
}
if ( s.dataType == "script" && s.cache == null )
s.cache = false;
/*if ( s.cache === false && type == "GET" ) {
var ts = now();
// try replacing _= if it is there
//alert(s.url) http://www.baidu.com?callback=jsonp1315980993828
var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
// if nothing was replaced, add timestamp to the end
s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
}*/
// If data is available, append data to url for get requests
if ( s.data && type == "GET" ) {
//加上其他的参数
s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
// IE likes to send both get and post data, prevent this
//ie的 get post 都会传送s.data 好像就是这个意思 所以节省开支
s.data = null;
}
// Watch for a new set of requests
//if ( s.global && ! jQuery.active++ )
// jQuery.event.trigger( "ajaxStart" );
// Matches an absolute URL, and saves the domain
//取url的 前面的信息 和 域名
var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
if ( s.dataType == "script" && type == "GET" && parts
&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = s.url;
if (s.scriptCharset)
script.charset = s.scriptCharset;
//如果不是jsonp方式 就是创建一个script标签
if ( !jsonp ) {
//保证回调函数只执行一次
var done = false;
// Attach handlers for all browsers 兼容所有的浏览器的写法
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
//success();
//complete();
// Handle memory leak in IE jq里面可以说反复的强调了 删除元素时 该dom元素引用的对象要断开引用 不然会内存泄露
script.onload = script.onreadystatechange = null;
head.removeChild( script );
}
};
}
head.appendChild(script);
// We handle everything using the script element injection
return undefined;
}
//创建一个新的对象 jq.ajaxSettings全部copy过去 把s复制过去
s = jq.extend(true, s, jq.extend(true, {}, jq.ajaxSettings, s));
var jsonp,
// jsonp 的回调函数名字要以这种方式才行
jsre = /=\?(&|$)/g,
status,
data,
type = s.type.toUpperCase();
//如果data不是字符串 转成字符串
if ( s.data && typeof s.data !== "string" )
s.data = jq.param(s.data);
if ( s.dataType == "jsonp" ) {
if ( type == "GET" ) {
if ( !s.url.match(jsre) ){
//get 方式 参数都在url的后面
//如果没有=?这种形式 就转成这种形式 这是jq的jsonp形式 后面要把?变成函数名
//转成这种形式 http://www.xxx.com?callback=?
s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
}//http://www.baidu.com?callback=?
} else if ( !s.data || !s.data.match(jsre) ){
//post方式 有专为存放参数的地方 这里是把参数和回调都转一下
//形式 xx=xx&oo=oo.......&callback=?
s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
}
s.dataType = "json";
}
// url 符合 定义的jsonp形式 或者 s.data符合jsonp形式
if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
// 这里的jsonp 就是后面的可执行函数的 函数名了
jsonp = "jsonp" + jsc++;
// Replace the =? sequence both in the query string and the data
// /=\?(&|$)/g
//将 ? 转 成函数名字
if ( s.data )
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
s.url = s.url.replace(jsre, "=" + jsonp + "$1");
s.dataType = "script";
// 定义全局的函数名了 后面请求完毕后就会执行这个函数
window[ jsonp ] = function(tmp){
data = tmp;
success();
//complete();
// Garbage collect
window[ jsonp ] = undefined;
try{ delete window[ jsonp ]; } catch(e){}
if ( head )
head.removeChild( script );
};
}
if ( s.dataType == "script" && s.cache == null )
s.cache = false;
/*if ( s.cache === false && type == "GET" ) {
var ts = now();
// try replacing _= if it is there
//alert(s.url) http://www.baidu.com?callback=jsonp1315980993828
var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
// if nothing was replaced, add timestamp to the end
s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
}*/
// If data is available, append data to url for get requests
if ( s.data && type == "GET" ) {
//加上其他的参数
s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
// IE likes to send both get and post data, prevent this
//ie的 get post 都会传送s.data 好像就是这个意思 所以节省开支
s.data = null;
}
// Watch for a new set of requests
//if ( s.global && ! jQuery.active++ )
// jQuery.event.trigger( "ajaxStart" );
// Matches an absolute URL, and saves the domain
//取url的 前面的信息 和 域名
var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
if ( s.dataType == "script" && type == "GET" && parts
&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = s.url;
if (s.scriptCharset)
script.charset = s.scriptCharset;
//如果不是jsonp方式 就是创建一个script标签
if ( !jsonp ) {
//保证回调函数只执行一次
var done = false;
// Attach handlers for all browsers 兼容所有的浏览器的写法
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
//success();
//complete();
// Handle memory leak in IE jq里面可以说反复的强调了 删除元素时 该dom元素引用的对象要断开引用 不然会内存泄露
script.onload = script.onreadystatechange = null;
head.removeChild( script );
}
};
}
head.appendChild(script);
// We handle everything using the script element injection
return undefined;
}
jQuery.ajax 的后面的部分就是处理ajax的了
jq有专门的设置请求头的部分
其中的 If-Modified-Since 比较重要了
jq里面用 jquery.lastModified 来保存最后的修改时间的
形式是 jquery.lastModified[url] = 时间
按我的理解是
我发送一次请求后 服务器看在 If-Modified-Since 里面的时间后有没有做修改,没有做修改返回304 读缓存的文件 有做修改返回200
这么做的好处是可以节约网络资源咯
jq1.3.2里面是设置的定时器 去判断请求是否已经完成
onreadystatechange是定时器去执行的函数
如果设置了s.timeout
会在这个时间后去查看是否已经xhr的状态 是否已经完成了回调 如果没有 abort 终止掉请求
jq还有一些方法配合 ajajx
jquery.httpSuccess
jquery.httpNotModified
jquery.httpData
jquery.httpSuccess
判断请求是否已经成功了
jquery.httpNotModified
判断 服务器那边是否已经做过了修改
jquery.httpData
因为返回的数据是根据请求头的content-type来的,所以要对不同的数据做处理
因为返回的数据是根据请求头的content-type来的,所以要对不同的数据做处理
在这里 又对 xml script json 的处理
其中script 用到了jquery.globalEval
在这里 又对 xml script json 的处理
其中script 用到了jquery.globalEval
一个完整的例子