【问题标题】:jQuery .on() method doesn't see new elementsjQuery .on() 方法看不到新元素
【发布时间】:2012-01-28 20:11:39
【问题描述】:

我正在获取一个 JSON 元素并从它的项目中构建一个列表,如下所示:

getTitles: function(data) {
    data = data || {};
    var list = [];

    $.getJSON(
        '/titles',
        data,
        function(data) {
            $.each(data.data, function(key, val) {
                list.push(
                    '<li><a href="'+ val.href +'">'+ val.title +'</a><span class="count">'+ val.count +'</span></li>'
                )
            });

            $('#title-items').html(list.join(''));
        }
    );
}

我正在为a 元素绑定点击事件,如下所示:

$('a').on('click', function(e) {
    alert('clicked');
    e.preventDefault();
});

旧的a 元素显示警报,但新元素跟随 URL。事件处理程序不适用于新的。我该如何解决这个问题?

【问题讨论】:

标签: javascript jquery event-handling click jquery-events


【解决方案1】:

您没有使用正确的代码来获得实时功能。

$('#title-items').on('click', 'a', function(e) {
    alert('clicked');
    e.preventDefault();
});
  1. 首先,选择您的共同祖先元素(本例中为#title-items)。如果你想处理 all a 元素,你也可以在这里使用document
  2. 传递事件类型(on),然后传递子选择器(a),然后传递事件的回调函数。

现在,当click 事件冒泡到#title-items 时,它会检查元素是否为a 元素,如果是,则触发回调。

【讨论】:

  • @cnkt:使用document 作为您的共同祖先元素。
  • @cnkt: 你必须使用 jQuery >= 1.7 才能使用.on()
  • @alex 这很不切实际吗?我的意思是,如果我在文档上附加了这个事件,那么它会在每次点击时触发这个功能,就像你说的那样。 :?:?:?
  • @gotqn 我想你可以稍微限制一下,这样它就不会使用
  • ...$('#title-items').on('click', 'li a', function(e) { alert('clicked'); e.preventDefault(); });
  • 附加到每个锚点
【解决方案2】:

您想使用事件委托来捕获在任何时间点出现在 DOM 中的事件上触发的事件:

$(<root element>).on('click', 'a', function(e) {
    alert('clicked');
    e.preventDefault();
});

更新 - 在此示例中,&lt;root element&gt; 是您要绑定的链接的祖先,在绑定时存在于 DOM 中。

基本思想是,由于我们无法将事件处理程序附加到尚未在 DOM 中的 DOM 元素,因此我们将事件处理程序附加到祖先元素并等待事件冒泡到祖先元素。一旦事件到达祖先事件,就会检查 event.target 属性以查看最初单击的元素是什么。

【讨论】:

  • @Gabe 我不知道用户的 HTML 结构是什么样的,所以这是对一般想法的演示。 .live() 也被贬值了,所以我不会在示例中使用它。
  • @Jasper: live() 从未真正受到赞赏!我想你的意思是 deprecated :P
  • @Gabe 这不取决于元素的嵌套程度吗?
  • @Jasper,是的,这取决于它的嵌套方式,如果你编辑你的答案,我会删除反对票,因为它不会让我直到你这样做......我只是认为可能会导致此示例的不良做法。另一个答案展示了更好的做法。
  • @Gabe 这是个好主意,我比其他答案更通用。
【解决方案3】:

您可以使用arrive.js 库(它在内部使用MutationObserver)。

document.arrive('a', function(){
    // 'this' refers to the newly created element
    var newElem = this;
});

【讨论】:

    【解决方案4】:

    关于接受的答案,请注意,如果您将 a 用作 jQuery 对象而不是 string - 如果您在 jQuery 选择器中犯了错误 - 事件将始终在 @ 987654324@ 被点击(无论a / p 等..)

    var a_links1 = $('a');
    var a_links2 = $('bla');
    
    $('#title-items').on('click', a_links1, function(e) {
        alert('clicked');   <= fire only on <a> elements
    });
    
    $('#title-items').on('click', a_links2, function(e) {
        alert('clicked');   <= fire on every element under <#title-items>
    });
    

    除非你会使用字符串

    $('#title-items').on('click', 'a', function(e) {
        alert('clicked');   <= fire only on <a> elements
    });
    
    $('#title-items').on('click', 'bla', function(e) {
        alert('clicked');   <= won't fire at all, as the selector won't match anything
    });
    

    jsFiddle:https://jsfiddle.net/7f8y5ak6/1/

    理解这一点很重要,因为当您期望将来添加 $('bla') 时(或在某些点击之后) - 但您在此之前加载了绑定事件 - jQuery 的选择器不会“找到”/ “看到”它们——那么当所有内容都可点击时,你就会出现这种行为。

    【讨论】:

      【解决方案5】:

      这个对我有用https://www.learningjquery.com/2017/02/jquery-on-method-the-issue-of-dynamically-added-elements

      用作直接事件的jQuery .on() 方法不适用于动态添加的元素。通过传递选择器参数使用委托事件,以便容器在将来动态添加元素的情况下负责执行事件。

      您可以将 .on 保留在 $(document).ready 内部或外部,这两个日志都可以使用!

      自定义标签

      $(document).on("click","[mycustomtag]", function(){
          console.log("Clicked.");
      });
      

      用于 HTML 类或 id 等

      $(document).on("click","div", function(){
          console.log("Clicked.");
      });
      

      【讨论】:

        猜你喜欢
        相关资源
        最近更新 更多
        热门标签