【问题标题】:JS function setting too many addEventListenersJS函数设置addEventListeners太多
【发布时间】:2020-03-25 19:55:02
【问题描述】:

我有一个具有搜索功能的单页应用程序 (SPA),我试图在其中跟踪用户如何与 Adob​​e Analytics 中的搜索栏进行交互。如果我导航到 SPA 的 5 个不同“页面”,以下代码将触发该事件 6 次。似乎addEventListener 正在设置但如果“页面”上没有发生搜索则不会被清除。每次加载“页面”时,这些事件监听器基本上都会排队,一旦输入搜索,它们就会同时触发,从而清除队列。

如果未执行搜索并且仅在通过按 Enter 执行搜索后才触发此事件,我如何清除 eventListeners?

假设我有代码:

clearInterval(interval);
var interval = setInterval(function(){
    if (document.querySelector("form div[data-autoid='search_bar'] input")) {       
        inputField = document.querySelector("form div[data-autoid='search_bar'] input")
        inputField.addEventListener('keydown', searchEntered)
        clearInterval(interval);
    } 
}, 500);

function searchEntered(e) {
    if (e.key == "Enter") {
      console.log("search entered");
      var event = new CustomEvent('searchEntered');
     dispatchEvent(event);
    }
}

【问题讨论】:

  • 间隔发生了什么?对于任何用例,这似乎都不是一个好的解决方案。
  • setEventListener() 不会移除已经添加的事件监听器。
  • @ScottMarcus - 在设置 eventListener 之前,间隔会监听搜索栏是否存在。
  • 这能回答你的问题吗? Event binding on dynamically created elements?

标签: javascript html dom-events addeventlistener event-listener


【解决方案1】:

如果要删除现有的事件侦听器,请使用EventTarget.removeEventListener()

正如MDN page 所述,您需要指定传递给addEventListener() 的相同typelistener 参数。如果您传递了选项,也应该将相同的选项传递给removeEventListener()

鉴于之前通过调用 addEventListener() 添加的事件侦听器,您最终可能需要将其删除。显然需要给removeEventListener()指定相同的type和listener参数,但是options或者useCapture参数呢?

虽然如果选项不同,addEventListener() 将允许您为同一类型多次添加相同的侦听器,但 removeEventListener() 检查的唯一选项是捕获/使用捕获标志。它的值必须匹配 removeEventListener() 才能匹配,但其他值不匹配。

请注意,不能将多个相同的侦听器添加到同一个元素。来自MDN page

如果多个相同的 EventListener 在同一个 EventTarget 上注册了相同的参数,则重复的实例将被丢弃。它们不会导致 EventListener 被调用两次,也不需要使用 removeEventListener() 方法手动移除。

【讨论】:

    【解决方案2】:

    如果您将事件侦听器添加到窗口,一旦发生这种情况,它将捕获页面(委托目标)上的所有 keydown 事件,然后检查它是否被触发通过 Enter 键,如果 parentNode 具有属性 data-autoid='search_bar'。 如果 true 调度您的自定义事件。

    即使 DOM 发生变化,这仍将继续工作

    addEventListener('keydown', e => {
      if (e.key == 'Enter' && e.target.parentNode.dataset.autoid == 'search_bar') {
        console.log('search entered');
        const event = new CustomEvent('searchEntered');
        dispatchEvent(event);
      }
    })
    <div data-autoid='search_bar'> 
      Will trigger <input />
    </div>
    
    <label>
      Won't trigger <input />
    </label>

    【讨论】:

      【解决方案3】:
      var interval = setInterval(function(){
        var inputField = document.querySelector("form div[data-autoid='search_bar'] input");
        if (inputField && !inputField.dataset.searchEventAttached) {
          inputField.addEventListener('keydown', searchEntered);
          inputField.dataset.searchEventAttached = true;
        } 
        clearInterval(interval);
      }, 500);
      

      【讨论】:

        猜你喜欢
        • 2011-10-09
        • 1970-01-01
        • 2020-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-14
        • 2017-05-04
        相关资源
        最近更新 更多