【问题标题】:Prevent onclick action with jQuery使用 jQuery 防止 onclick 动作
【发布时间】:2009-11-18 14:35:22
【问题描述】:

有一些带有 onclick 事件操作的链接

<a href="#" onclick="alert('panic!')">Let's panic</a>
<a href="#" onclick="alert('panic!')" disabled="disabled">I can't panic no more</a>

我需要阻止在具有 disabled 属性的链接上执行事件操作,而不删除 onclick 操作。

$('a[disabled]').click(function(e){
  e.stopPropagation();
  return false;
});

这段代码对我没有帮助。

更新即使这段代码也不起作用

<html><head><script type='text/javascript' src='jquery-1.3.2.js'></script></head>
<body>
<a href='#' onclick="alert('HA-ha!')" disabled="disabled" class="disabled">TEST</a>
<script type="text/javascript">
    $('a[disabled], a.disabled').click(function(e){
        console.log('override?');
        e.stopImmediatePropagation();           
            e.preventDefault();
        e.stopPropagation();
        return false;       
    });
</script>
</body></html>

【问题讨论】:

  • return false; vs. e.preventDefault(); vs e.stopPropagation(); 讨论在这里找到:stackoverflow.com/questions/1357118/…
  • 你所有的 jQuery 代码都应该被包裹在一个 $(document).ready( function() { ...code here... } ); 中,再加上从你的标记和选择器中删除 disabled 标记应该可以正常工作。

标签: javascript jquery events onclick


【解决方案1】:

jQuery 不会解决这个 OOTB。它可以提供帮助,但如果您只是将它们附加到元素上,stopPropagationstopImmediatePropagationpreventDefaultreturn false 将不起作用。您需要覆盖元素的点击处理程序。

但是您在问题中声明 “不删除 onclick 操作”。因此,您需要在触发事件时覆盖默认行为,(与简单的null为禁用的锚点删除onclick 属性相反的更简洁的方法):

这就是我的意思:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<title>Disable clicks</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
  <a href="#" onclick="alert('panic!')">Let's panic</a>
  <a href="#" onclick="alert('panic!')" disabled="disabled">I can't panic no more</a>

  <script>
  $('a[onclick]').each(function(){
    $(this).data('onclick', this.onclick);

    this.onclick = function(event) {
      if($(this).attr('disabled')) { // HERE
        return false;
      };

      $(this).data('onclick').call(this, event || window.event);
    };
  });
  </script>
</body>
</html>

Demo here.

方法是使用抢先逻辑覆盖内联点击处理程序 (onclick) 以捕获锚点“禁用”并然后取消事件的情况(使用return false) .

这样做的好处是,要再次启用锚点,您只需在其上 .removeAttr('disabled')

【讨论】:

  • 不错的清洁解决方案! event || window.event 是否必要,因为 jQuery 已经规范化了浏览器,而 event 对象在您的代码调用时是清理后的版本?
  • @dcneiner:是的,这是必需的。请注意,我们只是在浏览器调用的内联事件处理程序 (onclick) 中,不是处理程序 jQuery 规范化和调用。
  • 太棒了!感谢您的解决和解释。正是我需要的。
  • 我使用了eval(event.currentTarget.getAttribute('onclick')); 而不是$(this).data('onclick').call(this, event || window.event);。两种解决方案都有效。谢谢!
【解决方案2】:

disabled 不是锚的属性。请改用rel='disabled' 之类的东西。

$('a[rel="disabled"]').click( function() { return false; } );

更新

啊,当然。它仍然会触发alert,因为它实际上是内联在标记中的!我从来没有这样做过,所以没有注意到。将那个点击处理程序从标记中取出,并首先在 jQuery 中执行,这样您就可以执行以下操作:

$('a').click( function() {
  if( $(this).attr('rel') == 'disabled' ) { return; }
  // do stuff here when not disabled
  return false; // so your '#' href doesn't get used
} );

【讨论】:

  • 是的,jQuery 应该 能够使a[disabled="disabled"] 工作,但IMO 这是一个坏主意。坚持使用有效的标记:)
  • 无论如何,我已经尝试阻止使用一些名为 disabled 的类。它仍然什么都不做。
【解决方案3】:

问题是 jQuery 按顺序添加事件。要停止其他事件,您需要停止的事件必须在您的停止代码之后。由于您的点击中有代码,因此您需要更改顺序。这就是我会做的:

<a href='#' onclick="alert('HA-ha!')" class="disabled">TEST</a>
<a href='#' onclick="alert('HA-ha!')">TEST</a>
<script type="text/javascript">
    $('a').each(function(){
        // Cache event
        var existing_event = this.onclick;

        // Remove the event from the link
        this.onclick = null;

        // Add a check in for the class disabled
        $(this).click(function(e){ 
            if($(this).hasClass('disabled')){
                e.stopImmediatePropagation();
                e.preventDefault();
            }                
        });

        // Reattach your original onclick, but now in the correct order
        // if it was set in the first place
        if(existing_event) $(this).click(existing_event);
    });
</script>

好处只是使用 jQuery 删除/添加禁用的类:$('a#whatever').addClass('disabled') 或删除它$('a#whatever').removeClass('disabled'),不需要其他清理/设置。

【讨论】:

    【解决方案4】:

    任何由 jQuery 添加的点击处理程序似乎都会在标记中添加的那些处理程序之后触发。我的解决方案是使用 jQuery 而不是在标记中应用单击处理程序,但您可能没有足够的代码控制来执行此操作。如果你这样做了,那么就不要将点击处理程序应用于禁用类的锚标记(并且,是的,我会使用类而不是不适当的属性)。如果您无法控制标记,那么您可能希望使用 jQuery 替换单击处理程序,将其存储起来以供以后重新应用。

       $(function() {
          $('a.disabled').each( function() {
             var $this = $(this);
             var click = $this.attr('onclick');
             if (click) {
                 $this.data('click',click);
                 // add return false to prevent default action
                 $this[0].onclick =  function() { return false; };
             }
          });
    
          $('#restoreClick').click( function() {
              $('a.disabled').each( function() {
                  var $this = $(this);
                  $this.removeClass('disabled');
                  var click = $this.data('click');
                  if (click) {
                      $this[0].onclick = click;
                  }
              });
          });
       });
    

    测试:

    <div>
        <a href="#" onclick="alert('panic!')">Let's panic</a>
        <a href="#" onclick="alert('panic!')" class="disabled">I can't panic no more</a>
    </div>
    <div>
        <input type="button" id="restoreClick" value="Restore" />
    </div>
    

    【讨论】:

      【解决方案5】:

      我今天找到了一个非常简单的解决方案来防止点击,但如果需要,请保留该操作。

      <a href="javascript:alert('panic!')" >Let's panic</a>
      <a href="javascript:alert('panic!')" disabled="disabled">I can't panic no more</a>
      
      $('a').click(function(e){
          if($(this).attr('disabled')) e.preventDefault();
      });
      

      我不太喜欢使用“javascript:”,但这是迄今为止最简单的问题解决方案。

      希望对你有帮助!

      【讨论】:

      • I'm not a huge fan of using "javascript:", but this was by far the simplest solution to the problem. 你更喜欢其他客户端脚本语言吗?
      • 我喜欢 JavaScript,但我不喜欢使用带有“javascript:”语法的内联 javascript。 "javascript:alert('panic!')"
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多