【问题标题】:Using dynamically created .addEventListener's使用动态创建的 .addEventListener
【发布时间】:2019-02-16 11:14:34
【问题描述】:

抱歉,如果这是重复的,但在 www 上找到的答案没有回答我的具体问题,或者我只是缺乏找到正确答案的条件,如果是这样,我很乐意被引导到正确的方向。 :)

我的问题是,我从 .json 文件中获取一个数组,类似于:

[
    "Ben Berry",
    "Susan Boile",
    "Jerry Smith",
    ...
]

并为其制作一个局部变量副本,该副本将用于所有接下来的 script.js 工作。

让我们也想象一下,这个列表是巨大的。

在我的 HTML 中,我使用无序列表中的列表元素动态显示所有这些元素。

现在,如果有人点击其中一个 li,它应该从 DOM 中删除,并且元素的局部变量副本也应该删除。

这当然可以通过 li 标签内的 HTML 属性来完成 -> onclick=function() 但我觉得使用 addEventListener 方法更舒服。

这些监听器可以很容易地添加到每个监听器中,方法是使用 .forEach 循环整个数组并向每个 li 添加一个 eventListener。

但是,如果我现在按名字或姓氏的字母顺序对列表进行一次又一次的排序,会发生什么情况。这将导致一次又一次地调用包含这个 .forEach 循环的函数。

这个过程不会在内存中创建数十亿(没有双关语)的事件监听器,这会成为性能问题吗?如果是这样,最好的程序是什么?

【问题讨论】:

    标签: javascript arrays list performance addeventlistener


    【解决方案1】:

    使用 onclick 是 90 年代后期的遗留 JS,所以你偏爱addEventListener 解决方案是一件好事:你最初的想法是好的,但是将该侦听器添加到文档中,而不是添加到每个 li,并且然后检查哪个元素产生了事件:

    const ulElement = document.getElementByIdOrsomeCSSQueryOrSomething(...);
    
    ...
    
    document.addEventListener("click", evt => {
      // Only do things if the event source is an <li>, which we know
      // is the case if its parent node is our <ul> element:
      if (evt.target.parentNode === ulElement) {
    
        // remove the name from the list...
        let name = evt.target.textContent;
        removeName(name);
    
        // ... and remove the <li> from the DOM
        ulElement.removeChild(evt.target);
    
      }
    });
    

    (或者,您也可以将点击处理添加到列表本身,但如果您想要交换整个列表进/出,此代码只需要更新条件,而不是在显示时添加和删除事件侦听器/在页面上隐藏列表)

    【讨论】:

    • 只要注意&lt;li&gt;中是否还有其他元素...它们可能会成为目标
    • 谢谢,没想到这么多!但是,如果通过我的方法创建 addEventListeners 会出现性能问题吗?很抱歉我选择了其他答案作为解决方案,我想他可以比你更多地使用这些小点,但仍然感谢你所花的时间! @charlietfl 是的,我现在放置了一个带有两个条件的 if 语句,它应该只在特定条件下被接受。
    • 如果我关心积分,我就不应该在这里。诀窍是,在您知道您的“顶级”&lt;ul&gt; 是什么之后,您可以随时发出这个 addEventListener(单数,而不是复数)。不管它是否已经有'
    • '。
    【解决方案2】:

    您可以做的不是向每个项目添加事件,而是将事件添加到项目的父项并查找单击了哪个项目。这是一个例子:

    function setupListListener ()
    {
      // Get the list
      const list = document.querySelector( 'ul' );
      
      // Add click event
      list.addEventListener( 'click', () => {
        
        // Get the clicked element
        let target = event.target;
        
        // If it is not an item, return
        if ( target.nodeName !== 'LI' ) return;
        
        // Do something with the item li
        console.log( 'Item : ', target );
      
      });
    }
    
    // Usage example
    setupListListener();
    *
    {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }
    
    ul
    {
      width: 150px;
      list-style: none;
      border: 1px dashed #000;
    }
    
    li
    {
      width: 90%;
      height: 25px;
      display: flex;
      justify-content: center;
      align-items: center;
      margin: 10px auto;
      border: 1px solid #000;
      cursor: pointer;
    }
    <ul>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
    </ul>

    【讨论】:

    • 谢谢,没想到这么多!但是,如果 addEventListeners 是通过我的方法创建的,会不会出现性能问题?
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签