【问题标题】:disable click event for nested div elements until setTimeout is over禁用嵌套 div 元素的单击事件,直到 setTimeout 结束
【发布时间】:2020-08-27 16:25:24
【问题描述】:

我有这个脚本,我在其中突出显示单击的 div 及其父项,然后分别将它们再次变为白色。但是,我想停止连续点击,只允许一次点击直到 setTimeout 完成。基本上,用户应该等待整个动画完成后再点击。

const allDivElements = document.querySelectorAll("div");

let timeout = 300;
allDivElements.forEach((div) => {
  div.addEventListener("click", function (e) {
    setTimeout(() => {
      changeBg(this, true);
      setTimeout(() => {
        changeBg(this, false);
        timeout = 300;
      }, timeout);
    }, timeout);
    timeout += 300;
  });
});

function changeBg(div, phase) {
  if (phase) div.style.backgroundColor = "lightblue";
  else div.style.backgroundColor = "#fff";
}

就我查看可能的解决方案而言,在 setTimeout 方法之前,我无法找到阻止点击事件的解决方案。任何详细的帮助将不胜感激。

编辑:对不起,如果我造成混乱。这是整个应用程序的链接,以防您想测试它:https://codesandbox.io/s/busy-goldstine-ope9w?file=/src/index.js

提前致谢!

【问题讨论】:

    标签: javascript events nested click settimeout


    【解决方案1】:

    您似乎想让这变得过于复杂。只需为每个元素使用一个布尔值来跟踪点击是否应该起作用:

    const timeout = 300;
    allDivElements.forEach((div) => {
      let clickAllowed = true;
      div.addEventListener("click", function (e) {
        if (clickAllowed) {
          clickAllowed = false;
          changeBg(this, true);
          setTimeout(() => {
            changeBg(this, false);
            clickAllowed = true;
          }, timeout);
        } 
      });
    });
    

    【讨论】:

    • 这个脚本的问题是,在第二个setTimeout方法中,你再次用“clickAllowed = true”启用点击事件,这意味着即使在高亮过程中div元素不可点击,也会如此当它们再次变白时。
    • 这不是你想要的吗?
    • 我确实认为这就是您想要的 - 在超时期间防止点击。如果您真的想禁用 all 后续点击,那么您可以轻松删除该行 - 尽管添加事件处理程序比只使用一次更好更简单的方法。
    【解决方案2】:
    • 使用addEventListener 和removeEventListener 处理您的听众
    • 处理完所有元素后,使用addEventListener 添加回事件
    • 递归也可以方便地迭代父元素:

    const divs = document.querySelectorAll("div");
    const EVT = (el, t, n, f, o = {}) => el.forEach(e => e[`${{on:"add",off:"remove"}[t]}EventListener`](n, f, o));
    
    const changeBg = (div) => {
      if ([...divs].indexOf(div) < 0) return EVT(divs, "on", "click", clickHandler); // Add
      
      div.style.backgroundColor = "lightblue";
      setTimeout(() => {
        div.style.backgroundColor = "white";
        changeBg(div.parentElement); // Recursive call, this time pass the parent
      }, 300);
    };
    
    const clickHandler = async(ev) => {
      EVT(divs, "off", "click", clickHandler); // Remove listeners
      changeBg(ev.currentTarget); // Start
    };
    
    EVT(divs, "on", "click", clickHandler); // Add listeners
    body {
      font-family: sans-serif;
    }
    
    div {
      border: 1px solid black;
      padding: 5px;
      background: #fff;
    }
    <div id="1">1
      <div id="2">2
        <div id="3">3
          <div id="4">4
            <div id="5">5
            </div>
          </div>
        </div>
      </div>
    </div>

    【讨论】:

    • 这个答案很好,我一定会仔细阅读和理解!我想知道它是否适用于嵌套 div,因为这是我的情况。无论如何,我感谢您的帮助!也很抱歉没有添加任何额外的代码来指示我的布局。我刚刚添加了一个我在这个小项目上工作的代码框链接,如果你愿意,你也可以试试看我的意思
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多