Javascript 直接与委托 - jQuery .on()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8110934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:46:29  来源:igfitidea点击:

Direct vs. Delegated - jQuery .on()

javascriptjqueryevent-bubblingjquery-eventsevent-binding

提问by moey

I am trying to understand this particular difference between the directand delegatedevent handlers using the jQuery .on()method. Specifically, the last sentence in this paragraph:

我正在尝试使用jQuery .on()方法来理解直接委托事件处理程序之间的这种特殊区别。具体来说,本段最后一句:

When a selectoris provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.

selector提供 a 时,事件处理程序被称为delegated。当事件直接发生在绑定元素上时,不会调用处理程序,而是仅针对与选择器匹配的后代(内部元素)调用处理程序。jQuery 将事件从事件目标冒泡到附加处理程序的元素(即从最里面到最外面的元素),并为沿该路径匹配选择器的任何元素运行处理程序。

What does it mean by "runs the handler for any elements"? I made a test pageto experiment with the concept. But both following constructs lead to the same behavior:

“为任何元素运行处理程序”是什么意思?我做了一个测试页面来试验这个概念。但是以下两种结构都会导致相同的行为:

$("div#target span.green").on("click", function() {
   alert($(this).attr("class") + " is clicked");
});

or,

或者,

$("div#target").on("click", "span.green", function() {
   alert($(this).attr("class") + " is clicked");
});

Maybe someone could refer to a different example to clarify this point? Thanks.

也许有人可以参考一个不同的例子来澄清这一点?谢谢。

回答by N3dst4

Case 1 (direct):

案例1(直接):

$("div#target span.green").on("click", function() {...});

== Hey! I want every span.green inside div#target to listen up: when you get clicked on, do X.

== 嘿!我希望 div#target 中的每个 span.green 都能听到:当你被点击时,做 X。

Case 2 (delegated):

案例2(委托):

$("div#target").on("click", "span.green", function() {...});

== Hey, div#target! When any of your child elements which are "span.green" get clicked, do X with them.

== 嘿,div#target!当您单击“span.green”的任何子元素时,对它们执行 X 操作。

In other words...

换句话说...

In case 1, each of those spans has been individually given instructions. If new spans get created, they won't have heard the instruction and won't respond to clicks. Each span is directly responsiblefor its own events.

在情况 1 中,每个跨度都已单独给出指令。如果创建了新的跨度,他们将不会听到指令,也不会响应点击。每个跨度直接对其自己的事件负责

In case 2, only the container has been given the instruction; it is responsible for noticing clicks on behalf ofits child elements. The work of catching events has been delegated. This also means that the instruction will be carried out for child elements that are created in future.

在第2种情况下,只有容器被给予了指令;它负责代表其子元素注意到点击。捕捉事件的工作已经下放。这也意味着将针对将来创建的子元素执行该指令。

回答by nnnnnn

The first way, $("div#target span.green").on(), binds a click handler directly to the span(s) that match the selector at the moment that code is executed. This means if other spans are added later (or have their class changed to match) they have missed out and will not have a click handler. It also means if you later remove the "green" class from one of the spans its click handler will continue to run - jQuery doesn't keep track of how the handler was assigned and check to see if the selector still matches.

第一种方法,$("div#target span.green").on()在执行代码时将点击处理程序直接绑定到与选择器匹配的跨度。这意味着如果稍后添加其他跨度(或将它们的类更改为匹配),它们就会错过并且不会有点击处理程序。这也意味着如果您稍后从其中一个跨度中删除“绿色”类,其单击处理程序将继续运行 - jQuery 不会跟踪处理程序的分配方式并检查选择器是否仍然匹配。

The second way, $("div#target").on(), binds a click handler to the div(s) that match (again, this is against those that match at that moment), but when a click occurs somewhere in the div the handler function will only be run if the click occurred not just in the div but in a child element matching the selector in the second parameter to .on(), "span.green". Done this way it doesn't matter when those child spans were created, clicking upon them will still run the handler.

第二种方式,$("div#target").on()将点击处理程序绑定到匹配的 div(同样,这与当时匹配的 div 绑定),但是当点击发生在 div 中的某处时,处理程序函数只会在点击时运行不仅发生在 div 中,而且发生在与第二个参数中的选择器匹配的子元素中.on(),“span.green”。以这种方式完成这些子跨度的创建时间无关紧要,单击它们仍将运行处理程序。

So for a page that isn't dynamically adding or changing its contents you won't notice a difference between the two methods. If you are dynamically adding extra child elements the second syntax means you don't have to worry about assigning click handlers to them because you've already done it once on the parent.

因此,对于未动态添加或更改其内容的页面,您不会注意到这两种方法之间的区别。如果您正在动态添加额外的子元素,则第二种语法意味着您不必担心为它们分配点击处理程序,因为您已经在父元素上完成了一次。

回答by Brynner Ferreira

The explanation of N3dst4 is perfect. Based on this, we can assume that all child elements are inside body, therefore we need use only this:

N3dst4的解释很完美。基于此,我们可以假设所有子元素都在 body 内部,因此我们只需要使用这个:

$('body').on('click', '.element', function(){
    alert('It works!')
});

It works with direct or delegate event.

它适用于直接或委托事件。

回答by Bob Stein

Tangential to the OP, but the concept that helped me unravel confusion with this feature is that the bound elements must be parents of the selected elements.

与 OP 相切,但帮助我解开此功能混淆的概念是绑定元素必须是所选元素的父元素

  • Bound refers to what is left of the .on.
  • Selected refers to the 2nd argument of .on().
  • Bound 指的是.on.
  • Selected 是指 的第二个参数.on()

Delegation does not work like .find(), selecting a subset of the bound elements. The selector only applies to strict child elements.

委托不像 .find() 那样工作,选择绑定元素的子集。选择器仅适用于严格的子元素。

$("span.green").on("click", ...

is very different from

$("span").on("click", ".green", ...

In particular, to gain the advantages @N3dst4 hints at with "elements that are created in future" the bound element must be a permanent parent. Then the selected children can come and go.

特别是,要获得@N3dst4 暗示的“将来创建的元素”的优势,绑定元素必须是永久父元素。然后被选中的孩子可以来来去去。

EDIT

编辑

Checklist of why delegated .ondoesn't work

为何委派.on不起作用的清单

Tricky reasons why $('.bound').on('event', '.selected', some_function)may not work:

$('.bound').on('event', '.selected', some_function)可能不起作用的棘手原因:

  1. Bound element is not permanent. It was created after calling .on()
  2. Selected element is not a proper childof a bound element. It's the same element.
  3. Selected element prevented bubblingof an event to the bound element by calling .stopPropagation().
  1. 绑定元素不是永久的。它是在调用后创建的.on()
  2. 所选元素不是绑定元素的正确元素。这是同一个元素。
  3. 所选元素通过调用 来防止事件冒泡到绑定元素.stopPropagation()

(Omitting less tricky reasons, such as a misspelled selector.)

(省略不太棘手的原因,例如拼写错误的选择器。)

回答by Maciej Sikora

I wro te a post with a comparison of direct events and delegated. I compare pure js but it has the same meaning for jquery which only encapsulate it.

我写了一篇文章,比较了直接事件和委托。我比较了纯 js,但它对 jquery 具有相同的含义,只是封装了它。

Conclusion is that delegated event handling is for dynamic DOM structure where binded elements can be created while user interact with page ( no need again bindings ), and direct event handling is for static DOM elements, when we know that structure will not change.

结论是委托事件处理适用于动态 DOM 结构,其中可以在用户与页面交互时创建绑定元素(无需再次绑定),而直接事件处理适用于静态 DOM 元素,当我们知道结构不会改变时。

For more information and full comparison - http://maciejsikora.com/standard-events-vs-event-delegation/

有关更多信息和完整比较 - http://maciejsikora.com/standard-events-vs-event-delegation/

Using always delegated handlers, which I see is current very trendy is not right way, many programmers use it because "it should be used", but truth is that direct event handlers are better for some situation and the choice which method use should be supported by knowledge of differences.

使用始终委托的处理程序,我认为这是目前非常流行的方式,这不是正确的方式,许多程序员使用它是因为“应该使用它”,但事实是直接事件处理程序在某些情况下更好,并且应该支持选择使用哪种方法通过对差异的了解。