想知道当将onclick个侦听器设置为元素时,是否有一个性能/内存区域可以改进.

例子:

let btn = document.querySelector('.example')
btn.addEventListener('click', (e) => {
    btn.classList.add('active');
    btn.onmouseleave = () => {
        console.warn('leave')
    }
})

与之相比:

let btn = document.querySelector('.example')
btn.addEventListener('click', (e) => {
    e.target.classList.add('active');
    e.target.onmouseleave = () => {
        console.warn('leave')
    }
})

我认为使用btn需要更多的工作,因为计算机必须保存变量并记住它,而e.target临时使用事件.Which one is best for the least amount of memory consumption?

推荐答案

TL;TiM:活动委派*更好.

Event target vs currentTarget

Event.target might not be your btn Button.
Say the click casually landed on an icon inside of your button <button type="button">Contact <i class="icon-envelope"></i></button>, the Event.target would be — your icon!
To get your button Element (on which the handler is attached) use Event.currentTarget.

拇指法则非常简单:

  • Always use Event.currentTarget(即使建议不同,除非你真的、真的知道自己在做什么)
  • 在需要的时候使用Event.target,比如:从点击的地方获得最近的祖先(或self).一、 e:if (!evt.target.closest("#popup")) // Click landed outside of #popup. Close the popup-或使用活动委派时(稍后将详细介绍).

变量与参数性能

There's not much difference in performance in using a variable holding a single Element vs. the Event argument, other than perhaps memory and engine implementation.
If btn is a single Element stored in a variable, it already is the currentTarget: btn === e.currentTarget // always true therefore it's eventually up to your use case, and that's if you need to reuse the btn variable in other parts of the app, which would reduce queries to the DOM.
If instead btns is a huge NodeList, such as the one given back by const btns = ancestorElement.querySelectorAll("selector"), memory could be a factor.

on* event handlers are arguably bad

onmouseleave和其他on*处理程序应该是not be used-除非您正在从内存中创建(在一个非常小且可读的脚本中)全新的元素,或者您有意要覆盖之前分配的相同eventNameon*处理程序侦听器.

Use 100 instead和第三个参数选项{once: true}(如果只需要一次事件处理程序).

第三,改进版本:

const addActive = (evt) => {
  const elBtn = evt.currentTarget;
  elBtn.classList.add("active");
  elBtn.addEventListener("pointerleave", () => {
    console.log("leave");
  }, {once: true});
};

// Since you're using classes instead of ID,  
// make sure to refer to All of your elements by class,
// and assign an event listener to all of them:

const elsBtns = document.querySelectorAll('.example');

elsBtns.forEach((elBtn) => {
  elBtn.addEventListener("click", addActive);
});

或者如果需要"mouseleave"或"pointerleave"always:

const handleClick = (evt) => {
  const elBtn = evt.currentTarget;
  elBtn.classList.add("active");
};

const handleLeave = () => {
  console.log("leave");
};

const elsBtns = document.querySelectorAll('.example');

elsBtns.forEach((elBtn) => {
  elBtn.addEventListener("click", handleClick);
  elBtn.addEventListener("mouseleave", handleLeave);
});

活动委派

Say you have thousands of buttons. Storing them all in a variable might consume loads of memory (unless till the value is garbage collected). What better solution do we have?
Instead of a NodeList collection of N elements hanging in memory, and assigning to every single one a function handler for a specific Event: target a single common, static parent or ancestor:

document.querySelector("#commonParent").addEventListener("click", (evt) => {
  const elBtn = evt.target.closest(".example");
  if (elBtn) {
    // a .example ButtonElement was clicked.
    // Do something:  
    elBtn.classList.add("active");
  }
});

事件委派不仅很好,因为它是memory friendly,它还适用于添加到DOM中的当前或future 元素.

另外,这也是使用特定事件时最常用的另一种情况.目标-但正如您所看到的,它再次与Element.closest()方法相结合.

Javascript相关问答推荐

你怎么看啦啦队的回应?

用于编辑CSS样式的Java脚本

在open shadow—root中匹配时,使用jQuery删除一个封闭的div类

在JS中拖放:检测文件

从包含数百行的表中获取更改后的值(以表单形式发送到后端)的正确方法是什么?

我怎么在JS里连续加2个骰子的和呢?

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

Vaadin定制组件-保持对javascrip变量的访问

当标题被点击时,如何使内容出现在另一个div上?

自动滚动功能在当前图像左侧显示上一张图像的一部分

JavaScript&;Reaction-如何避免在不使用字典/对象的情况下出现地狱?

AG-GRIDreact 显示布尔值而不是复选框

FindByIdAndUpdate在嵌套对象中创建_id

如何按区域进行过滤并将其从结果数组中删除?

react :图表负片区域不同 colored颜色

Node.js的Fetch()调用总是创建新的Express会话

UseEffectreact 18-花很长时间进行API调用

导出JSON数据库以在JavaScript中使用

用对象填充数组的快速方法

如何在使用会话时防止争用情况?