2

我正在使用此代码创建一个 onshow 事件:

(function($){
  $.fn.extend({ 
    onShow: function(callback, unbind){
      return this.each(function(){
        var obj = this;
        var bindopt = (unbind==undefined)?true:unbind; 
        if($.isFunction(callback)){
          if($(this).is(':hidden')){
            var checkVis = function(){
              if($(obj).is(':visible')){
                callback.call();
                if(bindopt){
                  $('body').unbind('click keyup keydown', checkVis);
                }
              }                         
            }
            $('body').bind('click keyup keydown', checkVis);
          }
          else{
            callback.call();
          }
        }
      });
    }
  });
})(jQuery);

然后我叫它:

$(document).ready(function(){

    $('.mydiv').onShow(function(){
        alert('myDiv is now showing');

    });

});

我还切换了触发 div 显示和隐藏的链接:

$('.myLink').click(function(){
        $(".mydiv").slideToggle();
});

最后是html:

<a href="#" class="myLink">Step 1</a>
        <div class="myDiv">content here</div>

问题是,当我在页面加载后单击链接时,警报只显示一次。如果我再次单击它,我将不会显示。

任何想法为什么?

4

1 回答 1

1

我认为这是对事件如何在 javascript 中工作的误解。您的自定义扩展程序正在运行一次。该行$('body').bind('click keyup keydown', checkVis);侦听​​ click keyup 和 keydown 事件,但此侦听器仅应用于隐藏且已通过if($(this).is(':hidden')){检查的元素。

因此,如果有问题的元素开始隐藏,它将响应checkVis“单击 keyup 和 keydown”,但这是在onShow扩展完成第一次运行后运行任何东西的唯一实例。

.slideToggle();默认情况下不会触发任何事件,因此您的扩展程序无法侦听此类事件的触发。

最接近监听改变其可见性的元素是使用类似 dom 突变事件的东西,但这已被弃用并且不支持跨浏览器。

如果您真的需要能够在 jQuery“显示”元素时运行扩展,我能想到的最好方法是扩展您希望用来触发自定义事件的 jQuery 函数,它看起来像这样:

    var existingSlideToggle = $.fn.slideToggle;

    $.fn.slideToggle = function(){
         var returner = existingSlideToggle(this, arguments);
         $(this).trigger('customOnShowEvent');
         return returner;
    }

然后你可以这样做:

    $('#foo').on('customOnShowEvent', function(){  
       // do stuff 
    });

或者继续您的扩展策略:

(function($){
  $.fn.extend({ 
    onShow: function(callback, unbind){
      return this.each(function(){
        var obj = this;
        var bindopt = (unbind==undefined)?true:unbind; 

        var localRun = function(){
          if($(obj).is(':hidden')){
            var checkVis = function(){
              if($(obj).is(':visible')){
                callback.call();
                if(bindopt){
                  $('body').unbind('click keyup keydown', checkVis);
                }
              }                         
            }
            $('body').bind('click keyup keydown', checkVis);
          }
          else{
            callback.call();
          }
        }

        if($.isFunction(callback)){
            localRun();
            $(obj).on('customOnShowEvent', localRun);
        }

      });
    }
  });
})(jQuery);

这样它将第一次运行,然后在新的“customOnShowEvent”被触发(“触发”)时重新运行。

于 2012-10-18T16:53:20.053 回答