为具有特定类的当前和未来元素添加事件监听器

32

使用JQuery,是否可以为当前或将来具有特定类别的任何元素添加事件监听器?

我正在开发一个需要大量使用contentEditable的项目,因此DOM正在改变,并且元素可能会因用户输入而添加和删除类别。

我想能够说“类别X的元素在单击时应该执行Y”,但如果我理解正确,$(".X").click(Y)只会将事件监听器添加到当前具有类别X的元素。

此外,如果一个元素不再是类别X的一部分,则它仍将具有点击事件监听器。

如何实现这一点?


请查看on方法:http://api.jquery.com/on/ - Ilia G
3个回答

45

没错,你说的是事件委托。这里有一个示例:

$('#container').on('click', '.innerElement', function(){
   /// Do stuff
});

在你的情况下,#container 是一个已知存在于页面加载时包含你关心的子元素(现在或未来)的元素。这种方法利用了DOM中的事件冒泡。

正如另一位发帖者提到的,live方法也可以工作-但它已经在jQuery 1.7中弃用,并且通常不如使用更有选择性的委托方法(例如上面的示例)高效。


1
谢谢!我很感激上面清晰的解释……jQuery API网站确实需要整理一下它们某些东西的解释。不清晰的示例代码和含糊的解释只能让你走得更远。 - exoboy
你能告诉我如何仅使用JavaScript来完成相同的操作吗? - SHANK
@SHANK,如果你需要这个,我会说你需要jQuery。自己实现事件委托可能会很困难。如果你非常想尝试,基本上需要查看事件目标并尝试查看它是否与CSS选择器匹配。不过这并不是一件简单的事情。 - Kevin Ennis
如果您需要在监听器中使用 event.target 该怎么办?例如,如果我单击 .innerElement 中的元素 X,则事件将被分派(如预期),但 event.target 将是 #container(而 event.currentTarget 将是元素 X)。 - zok

5

如果您想要使用事件委托,可以采用以下类似的方式。在 jQuery 1.7 中,这种方式比以前更加抽象:

$("#myWrappingElement").on("click", ".myclass", function(event){
    alert($(this).text());
});

这基本上是向 #myWrappingElement 元素添加点击事件监听器,而jQuery会自动查看原始事件目标并触发适当的函数。这意味着您可以添加或删除 .myclass 元素,并仍然在它们上触发事件。

我假设 #myWrappingElement 可以是一个类而不是一个id? - sanity
可以是这个文档吗? - light24bulbs
@light24bulbs,是的,它可以。但是,在文档级别上有很多侦听器可能表明设计不良,所以要小心。 - nathan gonzalez

-1

jQuery的live()方法允许您拥有一个“实时”操作监听器 - 因此,如果新的DOM元素匹配选择器,则它们将附加到操作监听器。例如:

$(".X").live("click", function(){
    alert('some action');
});

查看此处的文档以获取更多信息:http://api.jquery.com/live/

我不确定你关于在删除类后保持操作监听器附加的第二部分是否可能 - 也许其他人有解决方案。


3
这是我第一次听说.live()从来没有很好地运行过。.delegate().live().bind()在jQuery 1.7+中被统一为.on(),因此如果要升级到jQuery 1.7+,应该在方便的时候切换到.on(),但可能有无数的页面使用.live()也运行得很好。 - jfriend00
@jfriend00,.live()已被弃用,不与.on()集成。如果您实际阅读链接给您的文档,您将看到使用live()的无数缺点和问题。 - nathan gonzalez
1
@nathangonzalez - .on().live() 的超集,旨在替代它。是的,我知道它已经被弃用了。这意味着你应该远离它,并且不要使用它编写新代码(如果你正在使用 jQuery 1.7+)。这并不意味着它已经失效或停止工作。而且,我发现很多人立即对建议使用 .live() 的人进行投票否决,这让我感到很烦。大部分世界甚至还没有开始使用 jQuery 1.7。关于 JQuery 1.7+ 中 .live() 被弃用并建议使用 .on() 的评论是可以的。 - jfriend00
2
@jfriend00,直接从jQuery API文档中复制: "自jQuery 1.7起,.live()方法已被弃用。使用.on()来附加事件处理程序。旧版本的jQuery用户应优先使用.delegate()。" 我认为这意味着永远不要使用.live()。 - nathan gonzalez
是的,有更好的方法可以通过限定到比文档对象更接近的父级作用域来完成,但 .live() 并不是无用或出故障的。它在无数个网页中运行良好。我同意使用更有效的方法(取决于jQuery版本)的建议,但你们认为.live() 无用或工作不好已经过了头。如果我有一堆使用 .live() 的工作网页,我会找不到理由立即中断新特性的开发并将它们改为 .on()。如果我要转移到jQuery 1.7,我会在方便的时候迁移到 .on() - jfriend00
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接