DOM 事件委托与否,哪个是最好的资源?
DOM event delegation or not, which is best resourcewise?
上下文:
- HTML 有很多行和很多列的长 table。
- 每个单元格包含附加元素和子元素。
- 在每行的最后一个单元格中,每行的按钮不同但相同
问题:
在此设置中,浏览器的资源方面(流动性、加载时间、响应能力等)最好:
- 在
<table>
元素上使用单个委托点击处理程序?这将通过点击任何其他单元格或子元素来触发,并且基本上会触发很多次,但什么也没有。
- 在每一行的每个
<button>
上使用事件处理程序?这将添加许多处理程序,但每个处理程序只在需要时 运行 一次。
- 另一种选择?
浏览器本身真的有区别吗? (不考虑编码实践)
在 (1) 委托情况下,浏览器是否必须为每个子元素添加一些侦听器才能知道它已被单击?
在您描述的情况下,事件委托的主要性能优势是
您只需连接一个处理程序一次,而不是遍历所有行来完成它。但是如果你有一个 table 太大以至于将处理程序连接到按钮是一个缓慢的操作,你可能会遇到其他性能问题 table.
A 次要 内存节省(事件注册)。
如果它是 click
处理程序,则无需担心性能劣势。 (例如,mousemove
处理程序可能并非如此。)
需要考虑代码的复杂性和维护问题(委派的处理程序 稍微 编写起来更复杂;如果添加了按钮,则将处理程序连接到每个按钮更容易出错在某些时候动态),但您说过您主要关心的是性能。
In the (1) delegate case, doesn't the browser have to somewhat add listeners to every child element to know it has been clicked ?
不,只有一个事件侦听器。点击 bubble 会发生什么。这是旧 DOM3 events spec (I can't find this diagram or an equivalent in the now-canonical WHAT-WG DOM spec 的图表,很不幸):
处理程序仅附加到一个元素。当点击冒泡(传播)到该元素时会发现它。
- Use a single delegate click handler on the
<table>
element ? This would be triggered by any click on any other cell or sub-element and basically triggered many more times for just nothing.
确实如此,但无害。所需的工作量几乎为零。
- Use an event handler on every
<button>
on every row ? This would add many handlers but each would run only once when needed.
您不需要很多 处理程序,您可以为多个按钮重复使用相同的功能。这只是处理程序的多个 注册:
function buttonHandler(event) {
// ...
}
// ...
for (const btn of document.querySelectorAll(".selector-for-button")) {
btn.addEventListener("click", buttonHandler); // Adds a registration, not
// an additional function
}
这不会为每个按钮创建新功能,它会为所有按钮重复使用相同的功能。在调用期间,event.currentTarget
将引用被单击的特定按钮(我们将处理程序连接到的按钮)。 (如果按钮有子元素,event.target
可能引用其中一个子元素,但 event.currentTarget
将引用按钮。)
因此,在任何给定情况下,您都必须权衡各种因素来决定要做什么。
上下文:
- HTML 有很多行和很多列的长 table。
- 每个单元格包含附加元素和子元素。
- 在每行的最后一个单元格中,每行的按钮不同但相同
问题:
在此设置中,浏览器的资源方面(流动性、加载时间、响应能力等)最好:
- 在
<table>
元素上使用单个委托点击处理程序?这将通过点击任何其他单元格或子元素来触发,并且基本上会触发很多次,但什么也没有。 - 在每一行的每个
<button>
上使用事件处理程序?这将添加许多处理程序,但每个处理程序只在需要时 运行 一次。 - 另一种选择?
浏览器本身真的有区别吗? (不考虑编码实践)
在 (1) 委托情况下,浏览器是否必须为每个子元素添加一些侦听器才能知道它已被单击?
在您描述的情况下,事件委托的主要性能优势是
您只需连接一个处理程序一次,而不是遍历所有行来完成它。但是如果你有一个 table 太大以至于将处理程序连接到按钮是一个缓慢的操作,你可能会遇到其他性能问题 table.
A 次要 内存节省(事件注册)。
如果它是 click
处理程序,则无需担心性能劣势。 (例如,mousemove
处理程序可能并非如此。)
需要考虑代码的复杂性和维护问题(委派的处理程序 稍微 编写起来更复杂;如果添加了按钮,则将处理程序连接到每个按钮更容易出错在某些时候动态),但您说过您主要关心的是性能。
In the (1) delegate case, doesn't the browser have to somewhat add listeners to every child element to know it has been clicked ?
不,只有一个事件侦听器。点击 bubble 会发生什么。这是旧 DOM3 events spec (I can't find this diagram or an equivalent in the now-canonical WHAT-WG DOM spec 的图表,很不幸):
处理程序仅附加到一个元素。当点击冒泡(传播)到该元素时会发现它。
- Use a single delegate click handler on the
<table>
element ? This would be triggered by any click on any other cell or sub-element and basically triggered many more times for just nothing.
确实如此,但无害。所需的工作量几乎为零。
- Use an event handler on every
<button>
on every row ? This would add many handlers but each would run only once when needed.
您不需要很多 处理程序,您可以为多个按钮重复使用相同的功能。这只是处理程序的多个 注册:
function buttonHandler(event) {
// ...
}
// ...
for (const btn of document.querySelectorAll(".selector-for-button")) {
btn.addEventListener("click", buttonHandler); // Adds a registration, not
// an additional function
}
这不会为每个按钮创建新功能,它会为所有按钮重复使用相同的功能。在调用期间,event.currentTarget
将引用被单击的特定按钮(我们将处理程序连接到的按钮)。 (如果按钮有子元素,event.target
可能引用其中一个子元素,但 event.currentTarget
将引用按钮。)
因此,在任何给定情况下,您都必须权衡各种因素来决定要做什么。