【问题标题】:Stop click event propagation on a label停止标签上的点击事件传播
【发布时间】:2020-04-17 13:59:53
【问题描述】:

我很难理解为什么单击标签时无法停止传播。

<label for="box">
    <input type="checkbox" id="box" />
    Test
</label>
$(function() {
    $('#box').on('click', checkbox);
    $('label').on('click', label);
});

function label(e) {
    console.log('label');
    e.stopPropagation();
}

function checkbox(e) {
    console.log('checkbox');
    e.stopPropagation();
}

当我单击标签时,尽管标签函数中有stopPropagation(),但仍会触发复选框函数。这是一个看似简单的问题,但解决方案似乎远没有那么简单......

【问题讨论】:

    标签: jquery events click stoppropagation


    【解决方案1】:

    这是因为这是浏览器的默认行为。您可以通过两种方式将复选框与标签关联:

    1. 标签内的复选框,例如:

      <label><input type="checkbox" id="box"/>Test</label>
      
    2. 或使用for 属性,如:

      <label for="box">Test</label><input type="checkbox" id="box"/>
      

    在这两种情况下,复选框将在标签点击时自动选中/取消选中。 w3.org中也提到了这一点。

    因此,为了防止这种默认操作,您应该使用event.preventDefault() 而不是在label 点击喜欢:

    $(function() {
      $('#box').on('click', checkbox);
      $('label').on('click', label);
    })
    
    function label(e) {
      e.preventDefault();
      console.log('label');  
    }
    
    function checkbox(e) {
      e.stopPropagation();
      console.log("checkbox");  
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <label for="box">
      <input type="checkbox" id="box"/>Test
    </label>

    如果您正在寻找更简单的解决方案,则可以将标签和复选框分开,并从标签中删除 for 属性,例如:

    <div class="wrapper">  
      <input type="checkbox" id="box"/>&nbsp;
      <label>Test</label>
    </div>

    【讨论】:

    • 非常好。我正要发布一个类似这样的答案。我更喜欢你的,palaѕн
    • 这里的问题是我需要默认行为。并且您的 preventDefault() 将不允许它。所以这个解决方案告诉我,没有什么真正干净的东西可以真正阻止传播。
    • @amo 您需要停止标签上click(由用户)的传播,然后在复选框上触发click(由浏览器)。因此,您只需要停止传播该事件即可。然后剩下的就是input 上的change 事件,从而产生所需的行为。
    【解决方案2】:

    这对我有用

    $('#box').on('change',function(e){
        console.log(e);
    });
    

    【讨论】:

      【解决方案3】:

      您需要停止在label 上传播click(由用户),然后在input 上触发click(由浏览器)。因此,您只需要停止传播该事件即可。那么剩下的就是input 上的change 事件,从而产生所需的行为。

      (还是有点烦,我知道……)

      在下面的 sn-p 中,请注意单击标签与单击复选框之间的区别!

      let input = document.getElementById('box');
      let label = document.getElementById('boxLabel');
      
      // Stop user click from propagating
      label.addEventListener('click', stopProp);
      // Stop browser click from propagating
      input.addEventListener('click', stopProp);
      
      function stopProp(e) {
          e.stopPropagation();
          console.log(e.target + ' Click stopped!');
      }
      
      input.addEventListener('change', function(e) {
          console.log(e.target + ' Value changed!');
      });
      <label id="boxLabel" for="box">
          <input type="checkbox" id="box"/>
          Test
      </label>

      或者,如果您不希望点击事件在输入端

      选项 A:设置标志

      let flag_ignoreNextClick = false;
      label.addEventListener('click', function() {
          flag_ignoreNextClick = true;
      });
      input.addEventListener('click', function() {
          if(flag_ignoreNextClick) {
              // Consume flag
              flag_ignoreNextClick = false;
              return;
          }
          //TODO do 'only on checkbox click' stuff here...
      });
      

      选项 B:模拟切换

      label.addEventListener('click', function(e) {
          // Prevent input click event
          e.preventDefault();
          // Emulate toggle
          input.checked ^= true;
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-20
        • 1970-01-01
        • 1970-01-01
        • 2016-05-18
        • 2021-03-25
        • 1970-01-01
        相关资源
        最近更新 更多