如何覆盖JQuery的.show()和.hide()来触发事件之前和之后的事件?

我尝试覆盖JQuery的.show和.hide方法,以便在使用以下代码调用它们之前和之后启动触发器事件。

$(document).ready(function () { $('#dataBox').bind('afterShow', function () { alert('afterShow'); }); $('#dataBox').bind('afterHide', function () { alert('afterHide'); }); $('#dataBox').bind('beforeShow', function () { alert('beforeShow'); }); $('#dataBox').bind('beforeHide', function () { alert('beforeHide'); }); $('#toggleButton').click(function(){ if($('#dataBox').is(':visible')) { $('#dataBox').hide (); } else { $('#dataBox').show(); } }); }); jQuery(function ($) { var _oldShow = $.fn.show; //Override jquery's 'show()' method to include two triggered events before and after $.fn.show = function (speed, oldCallback) { return $(this).each(function () { var obj = $(this), newCallback = function () { if ($.isFunction(oldCallback)) { oldCallback.apply(obj); } obj.trigger('afterShow'); }; obj.trigger('beforeShow'); _oldShow.apply(obj, [speed, newCallback]); }); } }); jQuery(function ($) { var _oldHide = $.fn.hide; //Override jquery's 'hide()' method to include two triggered events before and after $.fn.hide = function (speed, oldCallback) { return $(this).each(function () { var obj = $(this), newCallback = function () { if ($.isFunction(oldCallback)) { oldCallback.apply(obj); } obj.trigger('afterHide'); }; obj.trigger('beforeHide'); _oldHide.apply(obj, [speed, newCallback]); }); } }); 

我有以下标记:

   

当我点击切换按钮时,’beforeHide’和’beforeShow’事件正在触发,而’afterShow’和’afterHide’则没有。 谁能让我知道我做错了什么?

请检查演示小提琴 。 希望它有效

$ .show / $ .hide – 覆盖函数:

 (function($){ $.override ={'show': $.fn.show, 'hide': $.fn.hide}; $.each($.override,function(M,F){ var m=M.replace( /^\w/, function(r){ return r.toUpperCase(); }); $.fn[M] = function(speed, easing, callback) { var args=[speed||0,easing||'',callback||function(){}]; if( $.isFunction(speed)){ args[2]=speed; args[0]=0; } else if( $.isFunction(easing)){ args[2]=easing; args[1]=''; } if(!this.selector){ F.apply(this, arguments); return this; } return this.each(function () { var obj = $(this), oldCallback = args[args.length-1], newCallback = function () { if ($.isFunction(oldCallback)){ oldCallback.apply(obj); } obj.trigger('after'+m); }; obj.trigger('before'+m); args[args.length-1]=newCallback; //alert(args); F.apply(obj,args); }); } }); })(jQuery); 

用法

 jQuery(function($){ var $dataBox=$('#dataBox').bind('beforeHide afterHide beforeShow afterShow', function(e) { alert(e.type); }); $('#toggleButton').bind('click',function(){ $dataBox[$dataBox.is(':visible')?'hide':'show'](100,'swing',function(){ alert('end of animation');}); return false; }); }); 

我在你的代码中设置了一些断点,发现你永远不会调用newCallback函数。 多数民众赞成我认为因为你在调用该函数时没有使用速度参数。 从jQuery的原始函数doc $ .show中可以看到,你可以使用noonetwo或`three参数调用$.show

.show(持续时间[,回调])

duration一个字符串或数字,用于确定动画运行的时间。

callbackA动画完成后调用的函数。

版本新增:1.4.3

.show([duration] [,easing] [,callback])

duration一个字符串或数字,用于确定动画运行的时间。

easing一个字符串,指示要用于转换的缓动函数。

callbackA动画完成后调用的函数。

所以你可能会或可能不会传递一堆不同的参数。 所以我认为问题出在这一行

  _oldHide.apply(obj, [speed, newCallback]); 

在这种特定情况下, speed未定义。

你可以调用$.fn.show函数

 $(..).show(undefined,callBack) //or $(..).show(undefined,undefined, callBack) 

如果没有指定其他参数,回调将始终必须是第一个参数,在这种情况下,jQuery将使用它的动画默认的400ms速度/持续时间。 你会看到一个fadeIn / fadeOut类型的效果。 使其像使用此回调一样显示/隐藏

你必须像_oldShow/_oldHide一样调用

 _oldShow.apply(obj, [0,newCallback]); //or _oldHide.apply(obj, [0,newCallback]); 

在快速搜索中,我在互联网上找到了一个代码,它似乎运行正常,并且可以对所有可以传递给$.show$.hide $.show参数进行特殊处理。 检查以下小提琴,看看它

工作小提琴

为什么没有触发afterShowafterHide事件

如果显示/隐藏动画,jQuery将只调用回调函数(代码中的newCallback )。 如果没有参数传递给.show() / .show() (或者如果undefined speed ),那么jQuery将直接显示/隐藏元素,并且不会执行回调函数。

为什么覆盖.show() / .show()不是最好的主意

  • jQuery在内部调用.show() / .show() (例如作为.fadeTo()一部分)并递归调用(当进行动画显示/隐藏时),因此当您可能没有预期时会触发自定义事件。

  • 恕我直言,最好将“库存”jQuery和自定义分开(作为插件),使用单独的方法名称/命名空间:

    • 当您的开发人员在http://api.jquery.com中查找库存方法时,他们会知道文档完全描述了方法的行为。
    • 如果您的开发人员处理来自其他地方的代码,他们就不会调用stock方法并期望特定于公司代码库的行为。

.eventedShow() / .eventedHide()

这会添加.eventedShow().eventedHide() (它采用与.eventedHide()相同的参数)并且应该执行您想要的操作:

 (function( $ ) { $.each( [ 'Show', 'Hide' ], function( i, method ) { $.fn[ 'evented' + method ] = function( speed ) { var originalMethod = method.toLowerCase(), hasCallback = false, args; // animate if ( speed || speed === 0 ) { args = $.makeArray( arguments ); $.each( args, function( i, arg ) { if ( $.isFunction( arg ) ) { args[ i ] = function() { arg.apply( this, arguments ); $( this ).trigger( 'after' + method ); }; hasCallback = true; return false; } } ); if ( !hasCallback ) { args.push( function() { $( this ).trigger( 'after' + method ); } ); } this.each( function() { var el = $( this ); el.queue( function() { $( this ) .trigger( 'before' + method ) .dequeue(); } ); $.fn[ originalMethod ].apply( el, args ); } ); // straight show/hide } else { this.trigger( 'before' + method ); $.fn[ originalMethod ].apply( this, arguments ); this.trigger( 'after' + method ); } return this; }; } ); })( jQuery ); 

你可以在这里试试代码: http : //jsfiddle.net/jefferyto/bv8D2/

您仍然需要在现有代码eventedShow show / hide更改为eventedShow / eventedHide ,但这可以通过全局搜索和替换来完成。