动态创建的元素上的事件绑定?
我有一些代码,我循环遍历页面上的所有选择框,并将 .hover
事件绑定到它们,以便在鼠标开/关时对它们的宽度进行一些调整。
这发生在页面准备好并且工作得很好。
我遇到的问题是,在初始循环之后通过 Ajax 或 DOM 添加的任何选择框都不会绑定事件。
我找到了这个插件(jQuery Live Query Plugin),但在我添加另一个 5k 之前到我的带有插件的页面,我想看看是否有人知道一种方法来做到这一点,无论是直接使用 jQuery 还是通过其他选项。
I have a bit of code where I am looping through all the select boxes on a page and binding a .hover
event to them to do a bit of twiddling with their width on mouse on/off
.
This happens on page ready and works just fine.
The problem I have is that any select boxes I add via Ajax or DOM after the initial loop won't have the event bound.
I have found this plugin (jQuery Live Query Plugin), but before I add another 5k to my pages with a plugin, I want to see if anyone knows a way to do this, either with jQuery directly or by another option.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
从 jQuery 1.7 开始,您应该使用
jQuery.fn.on
并填充了选择器参数:解释:
这称为事件委托,工作原理如下。 该事件附加到应处理的元素的静态父级 (
staticAncestors
)。 每次在此元素或后代元素之一上触发事件时,都会触发此 jQuery 处理程序。 然后,处理程序检查触发事件的元素是否与您的选择器 (dynamicChild
) 匹配。 当存在匹配时,就会执行您的自定义处理程序函数。在此之前,推荐的方法是使用
live()
:但是,
live()
在 1.7 中已被弃用,取而代之的是on()
,并在 1.9 中完全删除。live()
签名:... 可以替换为以下
on ()
签名:例如,如果您的页面动态创建类名为
dosomething
的元素,您可以将该事件绑定到已存在的父级 strong> (这是问题的核心,您需要绑定到存在的东西,而不是绑定到动态内容),这可以是(也是最简单的选项)是document
。 但请记住文档
可能不是最有效的选择。事件绑定时存在的任何父级都可以。 例如
适用于
As of jQuery 1.7 you should use
jQuery.fn.on
with the selector parameter filled:Explanation:
This is called event delegation and works as followed. The event is attached to a static parent (
staticAncestors
) of the element that should be handled. This jQuery handler is triggered every time the event triggers on this element or one of the descendant elements. The handler then checks if the element that triggered the event matches your selector (dynamicChild
). When there is a match then your custom handler function is executed.Prior to this, the recommended approach was to use
live()
:However,
live()
was deprecated in 1.7 in favour ofon()
, and completely removed in 1.9. Thelive()
signature:... can be replaced with the following
on()
signature:For example, if your page was dynamically creating elements with the class name
dosomething
you would bind the event to a parent which already exists (this is the nub of the problem here, you need something that exists to bind to, don't bind to the dynamic content), this can be (and the easiest option) isdocument
. Though bear in minddocument
may not be the most efficient option.Any parent that exists at the time the event is bound is fine. For example
would apply to
jQuery.fn.on
的文档中有很好的解释。简而言之:
因此,在下面的示例中,
#dataTable tbody tr
在生成代码之前必须存在。如果新的 HTML 被注入到页面中,最好使用委托事件来附加事件处理程序,如下所述。
委派事件的优点是它们可以处理来自稍后添加到文档中的后代元素的事件。 例如,如果表存在,但使用代码动态添加行,则以下内容将处理它:
除了能够处理尚未创建的后代元素上的事件之外,委托事件的另一个优点是它们具有许多潜力。当必须监视许多元素时,可以降低开销。 在
tbody
中有 1,000 行的数据表上,第一个代码示例将处理程序附加到 1,000 个元素。委托事件方法(第二个代码示例)仅将事件处理程序附加到一个元素,即
tbody
,并且事件只需要向上冒泡一层(从单击的tr
代码>到tbody
)。注意:委托事件不适用于 SVG。
There is a good explanation in the documentation of
jQuery.fn.on
.In short:
Thus in the following example
#dataTable tbody tr
must exist before the code is generated.If new HTML is being injected into the page, it is preferable to use delegated events to attach an event handler, as described next.
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. For example, if the table exists, but the rows are added dynamically using code, the following will handle it:
In addition to their ability to handle events on descendant elements which are not yet created, another advantage of delegated events is their potential for much lower overhead when many elements must be monitored. On a data table with 1,000 rows in its
tbody
, the first code example attaches a handler to 1,000 elements.A delegated-events approach (the second code example) attaches an event handler to only one element, the
tbody
, and the event only needs to bubble up one level (from the clickedtr
totbody
).Note: Delegated events do not work for SVG.
这是一个纯 JavaScript 解决方案,没有任何库或插件:
其中
hasClass
是现场演示
归功于 Dave 和 Sime Vidas
使用更现代的 JS,
hasClass 可以实现为:
下面嵌入相同的 jsfiddle Live demo:
This is a pure JavaScript solution without any libraries or plugins:
where
hasClass
isLive demo
Credit goes to Dave and Sime Vidas
Using more modern JS,
hasClass
can be implemented as:The same jsfiddle Live demo embeded below:
您可以在创建对象时将事件添加到对象中。 如果要在不同时间向多个对象添加相同的事件,则创建命名函数可能是最佳选择。
You can add events to objects when you create them. If you are adding the same events to multiple objects at different times, creating a named function might be the way to go.
您可以简单地将事件绑定调用包装到一个函数中,然后调用它两次:一次在文档准备好时,一次在添加新 DOM 元素的事件之后。 如果您这样做,您将希望避免在现有元素上绑定相同的事件两次,因此您需要取消绑定现有事件或(更好)仅绑定到新创建的 DOM 元素。 代码看起来像这样:
You could simply wrap your event binding call up into a function and then invoke it twice: once on document ready and once after your event that adds the new DOM elements. If you do that you'll want to avoid binding the same event twice on the existing elements so you'll need either unbind the existing events or (better) only bind to the DOM elements that are newly created. The code would look something like this:
这是通过事件委托完成的。 事件将绑定在包装类元素上,但将委托给选择器类元素。 这就是它的工作原理。
和 HTML
#Note:
包装类元素可以是任何东西。 文件、正文或你的包装。 包装器应该已经存在。 但是,
selector
不一定需要在页面加载时呈现。 它可能会稍后出现,并且该事件将绑定在选择器
上不会失败。This is done by event delegation. Event will get bind on wrapper-class element but will be delegated to selector-class element. This is how it works.
And HTML
#Note:
wrapper-class element can be anything ex. document, body or your wrapper. Wrapper should already exist. However,
selector
doesn't necessarily needs to be presented at page loading time. It may come later and the event will bind onselector
without fail.尝试使用
.live()
而不是.bind()
; Ajax 请求执行后,.live()
会将.hover
绑定到您的复选框。Try to use
.live()
instead of.bind()
; the.live()
will bind.hover
to your checkbox after the Ajax request executes.动态创建的元素上的事件绑定
单个元素:
子元素:
注意添加的
*
。 该元素的所有子元素都会触发一个事件。我注意到:
它不再工作了,但以前可以工作。 我一直在使用 Google CDN 的 jQuery,但我不知道他们是否更改了它。
Event binding on dynamically created elements
Single element:
Child Element:
Notice the added
*
. An event will be triggered for all children of that element.I have noticed that:
It is not working any more, but it was working before. I have been using jQuery from Google CDN, but I don't know if they changed it.
我更喜欢使用选择器并将其应用到文档上。
这将自身绑定在文档上,并将适用于页面加载后将呈现的元素。
例如:
I prefer using the selector and I apply it on the document.
This binds itself on the document and will be applicable to the elements that will be rendered after page load.
For example:
您可以使用 live() 方法将元素(甚至是新创建的元素)绑定到事件和处理程序,例如 onclick 事件。
这是我编写的示例代码,您可以在其中看到 live() 方法如何将所选元素(甚至是新创建的元素)绑定到事件:
You can use the live() method to bind elements (even newly created ones) to events and handlers, like the onclick event.
Here is a sample code I have written, where you can see how the live() method binds chosen elements, even newly created ones, to events:
另一种解决方案是在创建元素时添加侦听器。 您可以在创建侦听器时将侦听器放置在元素中,而不是将侦听器放置在主体中:
Another solution is to add the listener when creating the element. Instead of put the listener in the body, you put the listener in the element in the moment that you create it:
尝试这样 -
Try like this way -
记下元素放置的“MAIN”类,例如,
在上面的场景中,jQuery 将监视的 MAIN 对象是“container”。
然后容器下基本上会有元素名称,例如
ul
、li
和select
:Take note of "MAIN" class the element is placed, for example,
In the above scenario, the MAIN object the jQuery will watch is "container".
Then you will basically have elements names under container such as
ul
,li
, andselect
:您可以在使用
jQuery(html, attribute)< 动态创建时将事件附加到元素/代码>
。
You can attach event to element when dynamically created using
jQuery(html, attributes)
.您可以使用
或者
这两种方法是等效的,但参数顺序不同。
请参阅: jQuery 委托事件
you could use
or
these two methods are equivalent but have a different order of parameters.
see: jQuery Delegate Event
这就是动态创建的元素不响应点击的原因:
作为解决方法,您必须监听所有点击并检查源元素:
这称为“事件委托”。 好消息,这是 jQuery 的内置功能:-)
Here is why dynamically created elements do not respond to clicks :
As a workaround, you have to listen to all clicks and check the source element :
This is called "Event Delegation". Good news, it's a builtin feature in jQuery :-)
绑定事件时存在的任何父父元素,并且如果您的页面使用类名按钮动态创建元素,则您将绑定已存在的父级事件
Any parent that exists at the time the event is bound and if your page was dynamically creating elements with the class name button you would bind the event to a parent which already exists
将事件绑定到已存在的父事件:
Bind the event to a parent which already exists:
使用 jQuery 的
.on()
方法 http://api.jquery.com/ on/ 将事件处理程序附加到活动元素。另外,从版本 1.9 开始,
.live()
方法被删除。Use the
.on()
method of jQuery http://api.jquery.com/on/ to attach event handlers to live element.Also as of version 1.9
.live()
method is removed.我更喜欢以模块化函数方式部署事件侦听器,而不是编写
文档
级别事件侦听器的脚本。 所以,我确实喜欢下面的。 请注意,您不能超额订阅具有相同事件侦听器的元素,因此不必担心多次附加侦听器 - 只有一个会粘住。I prefer to have event listeners deployed in a modular function fashion rather than scripting a
document
level event listener. So, I do like below. Note, you can't oversubscribe an element with the same event listener so don't worry about attaching a listener more than once - only one sticks.创建元素和绑定事件的另一个灵活的解决方案(源< /a>)
注意:这将为每个元素创建一个事件处理程序实例(在循环中使用时可能会影响性能)
Another flexible solution to create elements and bind events (source)
Note: This will create an event handler instance for each element (may affect performance when used in loops)
我正在寻找一种解决方案,使
$.bind
和$.unbind
在动态添加的元素中正常工作。由于 on() 巧妙地附加了事件,以便在那些我的事件上创建一个假的解除绑定来到:
I was looking a solution to get
$.bind
and$.unbind
working without problems in dynamically added elements.As on() makes the trick to attach events, in order to create a fake unbind on those I came to: