【问题标题】:A concise, simpler way to debounce the onclick event一种简洁、简单的方法来消除 onclick 事件的抖动
【发布时间】:2021-11-06 01:11:38
【问题描述】:

设置

我有一个移动用户界面,在视口的左下角有自己的UI 返回按钮

NB 在这种情况下,UI 是一个覆盖层,显示在 正在访问的网页之上,就像我是 History.pushState() 的粉丝一样, 在这个 在这种情况下,我并没有特别打算保持可导航的历史记录 使用History.pushState()覆盖视图。

如果用户已通过两个或更多视图进入 UI 叠加层,则无论何时单击或点按 UI 后退按钮,UI 叠加层都应显示上一个视图。


问题

我注意到我的 UI 后退按钮 可能非常敏感,并且很容易在不经意间与之交互,以至于 EventListener 认为它已被点击两次甚至三次,当用户的意图只是点击它一次


建议的解决方案

显然需要某种去抖动,因为我们可能更常使用onscrollonresize 事件。

在使用命名setTimeout() 函数和使用clearTimeout() 重复取消命名setTimeout() 之前,我已经编写了去抖动器,因此只有一个scrollresize 事件(最后一个)实际触发。

但在这种情况下,具有重复 clearTimeout() 函数的去抖动器感觉过于繁琐。


其他问题

理想情况下,我正在寻找一种简单、快速、简单、不冗长的方法来在检测到第一次点击后暂时停用EventListener

  • 我可以使用removeEventListener() - 但这需要在每次部署中,对原始addEventListener() 格式的具体了解

  • 我可以使用AbortSignal - 但这需要在原始addEventListener()options 参数中设置signal,我不能指望它

是否有一种简单通用的方法来消除onclick 事件的抖动?

【问题讨论】:

    标签: javascript dom-events onclicklistener debouncing


    【解决方案1】:

    有一种出人意料的简单方法去抖动onclick 事件,只需要两行javascript。

    该方法将 EventTarget 的 CSS pointer-events 属性设置为 none,然后稍后将其重置为 auto

    const myFunction = (e) => {
        
      e.target.style.setProperty('pointer-events', 'none');
      setTimeout(() => {e.target.style.setProperty('pointer-events', 'auto')}, 800);
        
      // REST OF FUNCTION HERE
    }
    

    工作示例:

    const myElement = document.querySelector('.my-element');
    
    const myFunction = (e) => {
        
      e.target.classList.add('unclickable');
      setTimeout(() => {e.target.classList.remove('unclickable')}, 2000);
        
      console.log('myElement clicked');
    }
        
    myElement.addEventListener('click', myFunction, false);
    .my-element {
      width: 100px;
      height: 100px;
      line-height: 100px;
      text-align: center;
      font-family: sans-serif;
      font-weight: 900;
      color: rgb(255, 255, 255);
      background-color: rgb(255, 0, 0);
      transition: opacity 0.3s linear;
      cursor: pointer;
    }
    
    .my-element.unclickable {
      opacity: 0.5;
      pointer-events: none;
    }
    <div class="my-element">Click me!</div>

    【讨论】:

    • 您也可以使用e.target.disabled 并将该属性设置在setTimeout() 上,我认为这样会更好
    • 感谢@JoshuaRDBrown - 这是表单元素的一个很好的替代建议。请注意,.disabled 属性只能应用于以下(表单)元素:<button><fieldset><input><optgroup><option><select><textarea>
    • 是的,很抱歉,我在查看实时代码 sn-p 后写下这句话,却忘了这不是按钮 onclick 事件
    • 不,这是我的错,@JoshuaRDBrown - 在上面的实时示例中,我使用了可点击的<div>,但在我自己的代码中(这引发了问题)我 使用<button>,您对e.target.disabled = true; 的建议可以正常工作。
    • 非常高兴我能帮上忙 :)
    猜你喜欢
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多