使用许多事件侦听器优化javascript性能

cor*_*raf 1 javascript optimization performance jquery event-listener

我目前正在构建一个允许搜索元素的站点,将结果添加到一个大表中(想想数百个结果).结果表中的每个元素都可以通过各种方式进行操作(自定义javascript 0-5星级,切换折叠面板以获取其他选项等).

如果我在我的Android平板电脑上使用该网站,javascript部分的性能非常低迷,所以我想知道如何提高性能.

我考虑的一个选项是不绑定结果行上的任何事件侦听器,除了单个鼠标输入事件,然后仅当鼠标位于给定元素上时绑定实际的事件侦听器.

任何其他提高性能的想法都将非常感激.

我的大多数javascript代码都是基于jquery的,所以如果你有任何jquery特定的优化,我也会很感激.

Nob*_*ita 9

您可以查看javaScript 事件委派.SO上有很多答案(这里有一个例子)和许多好文章(这里这里).

基本上你的想法实际上是一个很好的解决方案.所以,不是绑定 - 比方说 - 用他们自己的事件处理程序一百行,你绑定他们的共同父项,当它的任何一个孩子将接收鼠标输入时将触发一个事件.

粗略地说而不是这个:

$('tr').on("click", function() {});
Run Code Online (Sandbox Code Playgroud)

你会这样做:

$('table').on('click', 'tr', function() {});
Run Code Online (Sandbox Code Playgroud)

这显然是一个非常简单的例子,但它应该足以构建一个良好的模式.

作为旁注,这是一个非常有趣的事情(好吧,至少对我来说......)来检查被触发的事件,例如:

$('table').on('click', 'tr', function(evt) {
   console.log(evt);
});
Run Code Online (Sandbox Code Playgroud)

并查看事件所包含的信息量,以及通过简单的单击或鼠标输入即可获得多少有用的信息.

VanillaJs

当然,没有任何库可以实现相同的结果.

使用Vanilla JS的简单实现可以从David Walsh在答案开头链接的文章中获取,大致如下:

// Get the element, add a click listener...
document.getElementById("#myTable").addEventListener("click", function(e) {
    // e.target is the clicked element.
    // Check if it was a <tr>...
    if(e.target && e.target.nodeName == "TR") {
        // Element has been found, do something with it
    }
});
Run Code Online (Sandbox Code Playgroud)

如果你尝试这个代码虽然可能是实际target.element<td>,而不是<tr>我们想要的.这意味着我们必须更加聪明并向上走DOM以查看被点击的元素(<td>)是否包含在我们真正想要的那个(<tr>)中.

让您入门的粗略实现如下所示:

function walk(startEl, stopEl, targetNodeName) {
  if (!startEl || startEl === stopEl || startEl.nodeName === 'BODY') {
    return false;
  }

  if (startEl.nodeName === targetNodeName) {
    // Found it, return the element
    return startEl;
  }

  // Keep on looking...
  return walk(startEl.parentNode, stopEl, targetNodeName);
}

const container = document.getElementById('myTable');

container.addEventListener('click', (e) => {
  const clickedElm = walk(e.target, container, 'TR');
  console.log(clickedElm);
  if (clickedElm) {
    clickedElm.classList.add('clicked');
  }
})
Run Code Online (Sandbox Code Playgroud)

看到这个小提琴或下面的片段:

function walk(startEl, stopEl, targetNodeName) {
  if (!startEl || startEl === stopEl || startEl.nodeName === 'BODY') {
    return false;
  }

  if (startEl.nodeName === targetNodeName) {
    return startEl;
  }

  return walk(startEl.parentNode, stopEl, targetNodeName);
}

const elem = document.getElementById('myTable');

elem.addEventListener('click', (e) => {
  const clickedElm = walk(e.target, elem, 'TR');
  console.log(clickedElm);
  if (clickedElm) {
    clickedElm.classList.add('clicked');
  }
})
Run Code Online (Sandbox Code Playgroud)
table {
  width: 100%;
}
tr {
  background: #ddd;
}
.clicked {
  background: teal;
}
Run Code Online (Sandbox Code Playgroud)
 <table id="myTable">
   <tr>
     <td>one</td>
   </tr>
   <tr>
     <td>two</td>
   </tr> 
   <tr>
     <td>three</td>
   </tr> 
   <tr>
     <td>four</td>
   </tr> 
   <tr>
     <td>five</td>
   </tr> 
   <tr>
     <td>six</td>
   </tr>    
 </table>
Run Code Online (Sandbox Code Playgroud)