使用动态创建的.addEventListener的

时间:2018-09-11 21:40:48

标签: javascript arrays list performance addeventlistener

很抱歉,如果这是重复的,但是在www上找到的答案没有回答我的特定问题,或者我只是缺少找到正确答案的条件,如果是的话,我很乐意为您提供指导。正确的方向。 :)

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

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

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

我们还可以想象,这个列表是巨大的。

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

现在,如果有人单击这些li之一,则应将其从DOM中删除,并且也应删除该元素的局部变量副本。

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

通过使用.forEach遍历整个数组并将事件侦听器添加到每个li,可以轻松地将这些侦听器添加到其中的每个侦听器。

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

此过程是否会在内存中创建数千亿(无双关)的事件监听器,这会成为性能问题?如果是这样,最好的程序是什么?

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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);

  }
});

(或者,您也可以将点击处理添加到列表本身,但是如果您要交换整个列表的输入/输出,则此代码只需要更新条件,而不是像显示/添加事件监听器/隐藏页面上的列表)