1 /*重写Jquery中的ajax 封装壳*/ 2 $(function () { 3 (function ($) { 4 //首先备份下jquery的ajax方法 5 var _ajax = $.ajax; 6 7 //重写jquery的ajax方法 8 $.ajax = function (opt) { 9 //备份opt中error和success方法 10 var fn = { 11 beforeSend: function (XHR) { }, 12 error: function (XMLHttpRequest, textStatus, errorThrown) { }, 13 success: function (data, textStatus) { }, 14 complete: function (XHR, TS) { } 15 } 16 17 if (opt.beforeSend) { 18 fn.beforeSend = opt.beforeSend; 19 } 20 if (opt.error) { 21 fn.error = opt.error; 22 } 23 if (opt.success) { 24 fn.success = opt.success; 25 } 26 if (opt.complete) { 27 fn.complete = opt.complete; 28 } 29 30 31 32 //扩展增强处理 33 var _opt = $.extend(opt, { 34 //全局允许跨域 35 xhrFields: { 36 withCredentials: true 37 }, 38 error: function (XMLHttpRequest, textStatus, errorThrown) { 39 //错误方法增强处理 40 fn.error(XMLHttpRequest, textStatus, errorThrown); 41 }, 42 success: function (data, textStatus) { 43 //成功回调方法增强处理 44 fn.success(data, textStatus); 45 }, 46 beforeSend: function (XHR) { 47 //提交前回调方法 48 fn.beforeSend(XHR); 49 }, 50 complete: function (XHR, TS) { 51 //请求完成后回调函数 (请求成功或失败之后均调用)。 52 fn.complete(XHR, TS); 53 } 54 }); 55 if (opt.xhrFields) { 56 _opt.xhrFields = opt.xhrFields; 57 } 58 59 //调用native ajax 方法 60 return _ajax(_opt); 61 }; 62 })(jQuery); 63 });
jquery之重写(扩展)$.ajax和$.fn.load等方法详解
今天做东西,考虑用户最好的体验,要实现界面上异步请求数据的loading效果,功能代码都是别人写完的,大概几十个地方,用的都是jQuery的load方法。咋整啊,总不能挨个去每个方法里面加效果吧,几十个地方呢。思来想去,只能用重写了,嘛也不说了,开干。
作为一名资深小白,之前从未重写过jQuery的方法,依托着度娘,外加又看了看jquery的源码,终于把问题解决了。所以以此博文,来小总结下学到的知识亦或帮助“同病相怜”的人,部分资源摘自网络,如有纰漏,还望海涵并指出。
一、前提知识
往下翻页之前,有必要了解以下知识:
1. (function($){….})(jQuery)
第一个括号里边的function($){….}实际上就是一个匿名函数,它的形参是$,这很奇怪,其实这里主要是为了不与其它的库冲突。我们在调用函数的时候,通常都是函数名后边加上括号以及实参,但是由于操作符的优先级我们定义的匿名函数也需要用()括起来,所以就有了前面的(function($){….})。
现在这句代码什么意思大家应该很清楚了:第一个括号表示定义了一个匿名函数,然后(jQuery)表示为该函数传递的参数,整个结合起来意思就是,定义了一个匿名函数,然后又调用该函数,并传递实参jQuery,相当于——function fun($){…};fun(jQuery);
这种方法多用于存放开发的插件,执行其中的代码时,Dom对象并不一定加载完毕。于此相反的是$(function(){}),这种方法在使用时页面的Dom对象已经加载完毕了。事实上该方法的全写是:$(document).ready(function(){});
2.$.fn.extend和$.extend
jQuery为开发插件提拱了两个方法,分别是:
jQuery.fn.extend(object);//为jQuery的实例对象添加方法
jQuery.extend(object);//为jQuery类本身扩展,添加新的方法或覆盖原有的方法
(1)$.fn.extend
在jQuery中有如下源码:
[javascript] view plain copy
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {//….
//……
};
由此看来jQuery.fn=jQuery.prototype,然而prototype是什么呢?
在 JavaScript 中,每个函数对象都有一个默认的属性 prototype,称为函数对象的原型成员,这个属性指向一个对象,称为函数的原型对象,当我们每定义了一个函数的时候,JavaScript 就创建了一个对应的原型对象,也就是说,当我们定义一个函数的时候,实际上得到了两个对象,一个函数对象,一个原型对象。原型对象是一个特殊的对象,函数的 prototype 成员指向它的原型对象,可以通过函数对象的 prototype 成员取得这个原型对象的引用。
所以fn表示的就是原型对象,而extend表示扩展,所以$.fn.extend表示的是为原型对象扩展方法,使用此方式扩展的方法只能用对象去调用,example:
[javascript] view plain copy
$.fn.extend({
test:function(){
alert(“test”);
}
});
$(“#id”).test();
(2)$.extend
此方式则表示为jQuery类添加类方法(虽然jQuery没有类的概念,但用类来理解似乎简单了不少),或者直接理解为添加静态方法,然后就可以直接用$在其他地方来调用此扩展方法了,example:
[javascript] view plain copy
$.extend({
test:function(param){
alert(param);
}
});
$.test(1);//则直接弹出1
3. JavaScript的闭包
闭包是js的难点也是js的特色,很多高级应用都要依靠闭包来实现,网络资源很多,在这里不在赘述,最好也去了解下。
4.JavaScript的apply方法以及call方法
这两个概念也是有必要知道的,详见我转载的文章:点击这里
二、重写方法
1.重写$.ajax方法
[javascript] view plain copy
(function($){
//首先备份下jquery的ajax方法
var_ajax=$.ajax;
//重写jquery的ajax方法
$.ajax=function(opt){
//备份opt中error和success方法
var fn = {
error:function(XMLHttpRequest, textStatus, errorThrown){},
success:function(data, textStatus){}
}
if(opt.error){
fn.error=opt.error;
}
if(opt.success){
fn.success=opt.success;
}
//扩展增强处理
var_opt = $.extend(opt,{
error:function(XMLHttpRequest, textStatus, errorThrown){
//错误方法增强处理
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success:function(data, textStatus){
//成功回调方法增强处理
fn.success(data, textStatus);
},
beforeSend:function(XHR){
//提交前回调方法
$(‘body’).append(“<div id=’ajaxInfo’ style=”>正在加载,请稍后…</div>”);
},
complete:function(XHR, TS){
//请求完成后回调函数 (请求成功或失败之后均调用)。
$(“#ajaxInfo”).remove();;
}
});
return _ajax(_opt);
};
})(jQuery);
2.重写$.load方法
[javascript] view plain copy
//同样先备份下jquery的load方法
var _load=$.fn.load;
$.fn.extend({
load:function(url,param,calbck){
//其他操作和处理
//..
//此处用apply方法调用原来的load方法,因为load方法属于对象,所以不可直接对象._load(…)
return _load.apply(this,[url,param,calbck]);
}
});