单击事件不适用于动态生成的元素 [重复]

Click event doesn't work on dynamically generated elements [duplicate]

提问人:cheng 提问时间:7/12/2011 最后编辑:Cᴏʀʏcheng 更新时间:7/20/2023 访问量:647434

问:

<html>
<head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">

        $(document).ready(function() {

            $("button").click(function() {
                $("h2").html("<p class='test'>click me</p>")
            });   

            $(".test").click(function(){
                alert();
            });
        });

    </script>
</head>
<body>
    <h2></h2>
    <button>generate new element</button>
</body>
</html>

我试图通过单击按钮生成一个带有类名的新标签。我还定义了一个与 关联的点击事件。但该事件不起作用。test<h2>test

谁能帮忙?

jQuery 事件

评论

0赞 Keelx 7/12/2011
尝试使用 <input id=“button” type=“button” value=“generate new element”>。它将一个新 ID 注册到 DOM 中,jQuery 可以访问该 ID,而 <button>则不能。
3赞 Josef Engelfrost 4/30/2014
注意:在有效的 HTML 中,您不能将 <p> 放在 <h2> 中
0赞 Satinder singh 8/17/2015
这是一篇关于如何为动态元素 goo.gl/zlEbnv 绑定点击事件的详细文章
0赞 Prem 10/9/2016
这段视频帮助 youtube.com/watch?v=unk-U_LQWuA

答:

803赞 Cᴏʀʏ 7/12/2011 #1

您使用的绑定称为“直接”绑定,它只会将处理程序附加到已存在的元素。它不会绑定到将来创建的元素。为此,您必须使用 on() 创建一个“委托”绑定。click()

委托事件的优点是,它们可以处理来自稍后添加到文档中的后代元素的事件。

以下是您要查找的内容:

var counter = 0;

$("button").click(function() {
    $("h2").append("<p class='test'>click me " + (++counter) + "</p>")
});

// With on():

$("h2").on("click", "p.test", function(){
    alert($(this).text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<h2></h2>
<button>generate new element</button>

以上适用于使用jQuery版本1.7+的用户。如果您使用的是旧版本,请参阅下面的上一个答案。


上一个答案

尝试使用 live():

$("button").click(function(){
    $("h2").html("<p class='test'>click me</p>")
});   


$(".test").live('click', function(){
    alert('you clicked me!');
});

为我工作。用 jsFiddle 试过了

或者有一种使用 delegate() 的新奇方法:

$("h2").delegate("p", "click", function(){
    alert('you clicked me again!');
});

更新的 jsFiddle

评论

9赞 Dave Jarvis 11/5/2012
从 jQuery 1.7 开始,该方法已弃用。用于附加事件处理程序。.live().on()
71赞 Blake Plumb 4/26/2013
它需要或绑定到其他父母才能等于 Only 说,因为它出现在最近的一个问题$(document).on('click', '.test', function() {.live
2赞 Cᴏʀʏ 4/26/2013
@BlakePlumb:我查看了jQuery文档;你是对的!我会更新我的答案。感谢您的留言!
1赞 Dylan Glockler 12/9/2021
确保您选择的可点击父元素是在页面加载时呈现的元素,而不是动态生成的元素 - 是的,这很明显,但如果你没有想清楚,它可能会像我一样让你犯规一分钟!
0赞 noraj 8/25/2022
Blake Plumb 是对的,如果你读过 api.jquery.com/on 它说: > 事件处理程序仅绑定到当前选定的元素;在代码调用 时,它们必须存在。[...]> 委托事件处理程序的优点是,它们可以处理以后添加到文档中的后代元素中的事件。[...]此元素可以是容器元素 [...],或者如果事件处理程序想要监视文档中的所有冒泡事件。.on()document
13赞 amurra 7/12/2011 #2

您需要使用 .live 才能正常工作:

$(".test").live("click", function(){
   alert();
});

或者,如果您使用的是 jQuery 1.7+,请使用 .on

$(".test").on("click", "p", function(){
   alert();
});

评论

0赞 Roko C. Buljan 4/9/2013
请阅读有关委派事件的文档。您的活动委托元素在哪里?您展示的另一个示例(使用 .on())在任何情况下都不是替换的确切方法。.live()
13赞 qwertymk 7/12/2011 #3

改变

 $(".test").click(function(){

 $(".test").live('click', function(){

现场演示

jQuery .live()

评论

0赞 Prabhagaran 7/10/2021
我猜live()已弃用
8赞 DSKrepps 7/12/2011 #4

Try 或.live().delegate()

http://api.jquery.com/live/

http://api.jquery.com/delegate/

您的元素是在方法之后添加的,因此它没有附加事件。Live 和 Delegate 将该事件触发器提供给检查其子元素的父元素,因此之后添加的任何内容仍然有效。我认为 Live 会检查整个文档正文,而 Delegate 可以赋予元素,因此 Delegate 效率更高。.test.click()

更多信息:

http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/

评论

0赞 T J 8/23/2014
从 jQuery 1.71 开始,已弃用并被 .on() 方法取代.live()delegate()
4赞 Marc LaFleur 7/12/2011 #5

您遇到的问题是,您尝试将“test”类绑定到事件,然后才发现 .尽管这看起来都是动态的,但实际发生的是,当函数触发时,传递并连接单击事件,这发生在您在按钮事件中创建“单击我”之前。DOMJQueryDOMready()

通过将 “test” Click 事件添加到 “button” click 处理程序中,它将在 中存在正确的元素后将其连接起来。DOM

<script type="text/javascript">
    $(document).ready(function(){                          
        $("button").click(function(){                                  
            $("h2").html("<p class='test'>click me</p>")                          
            $(".test").click(function(){                          
                alert()                          
            });       
        });                                     
    });
</script>

使用(正如其他人指出的那样)是另一种方法,但我觉得指出 JS 代码中的小错误也是一个好主意。你写的没有错,只是需要正确的范围。掌握 和 JS 的工作原理是许多传统开发人员需要解决的棘手问题之一。live()DOM

live()是一种更清洁的处理方法,在大多数情况下是正确的方法。它本质上是在观察事物并在其中的元素发生变化时重新布线。DOM

3赞 Ankit Tanna 1/8/2013 #6

.live 函数效果很好。

它用于动态添加到舞台上的元素。

$('#selectAllAssetTypes').live('click', function(event){
                    alert("BUTTON CLICKED");
                    $('.assetTypeCheckBox').attr('checked', true);
                });

干杯 安基特。

评论

3赞 Liam 4/8/2013
从 Jquery 1.7 开始,Live 已被弃用,取而代之的是 .on。它甚至从 Jquery 1.9 开始被删除。api.jquery.com/live
269赞 Roko C. Buljan 1/26/2013 #7

将 jQuery 的 .on() 方法与委托事件一起使用

$(".staticParent").on("click", ".dynamicChild", function(evt) {
  // Existent or future .dynamicChild element was clicked

  console.log($(this));            // $ Object {.dynamicChild}
  console.log(this);               // Element .dynamicChild
  console.log(evt.currentTarget);  // Element .dynamicChild
  console.log(evt.target);         // Element .dynamicChild or any descendant
  console.log(evt.delegateTarget); // Element .staticParent delegator
});

.on() 方法允许您将任何所需的事件处理程序委托给:
当前元素或以后添加到 DOM 的未来元素。

附加通知:从 jQuery v1.7+ 开始,该方法优先于已弃用的 ..on().live()

JavaScript 中的事件委派

作为技术参考,以下是使用纯 JavaScript 正确实现事件委派的方法:

document.querySelectorAll(".staticParent").forEach((elStaticParent) => {
  elStaticParent.addEventListener("click", (evt) => {
    const elDynamic = evt.target.closest(".dynamicChild");
    if (!elDynamic) return; // .dynamicChild not clicked. Do nothing.

    // Existent or future .dynamicChild element was clicked

    console.log(elDynamic);         // Element .dynamicChild
    console.log(evt.target);        // Element .dynamicChild or any descendant
    console.log(evt.currentTarget); // Element .staticParent delegator
  });
});

对于从 jQuery 切换到纯 JavaScript 的开发人员来说,Event 参数(在上面的例子中)的差异经常令人困惑。 在jQuery中是一个构造的自定义对象,它提供了一些属性,例如可以轻松访问委托事件(以及许多其他事件)的静态父级。在 JavaScript 中,参数不提供此类属性。相反,您可以使用以下命令访问它(这在jQuery中也有所不同)。
在 JavaScript 中(目前仍在使用),我们需要添加一个额外的检查(通常作为语句)来检测接收 Event 的所需动态子项,这是通过使用 .如果检索到这样的元素,这意味着它自己、它的子元素或任何更深层次的后代都冒泡了这样的事件。在将 Event 分配给元素时,这种方法至关重要,例如: ,即使指针的目标是按钮的图标 Element,它也能确保正确通过检查。
一些实现建议使用 i.e: 从长远来看,这很容易出现错误(将子元素添加到动态元素并观察您的 JS 失败)。对于同样错误和不准确的建议也是如此。
在不深入技术细节的情况下,请确保了解差异,以便构建坚如磐石的实现。
evt$.EventdelegateTargetEventEvent.currentTargetifEvent.target.closest("someSelector")<button class="dynamicBtn" type="button">Click me <i class="icon-star"></i></button>evt.target && evt.target.matches("someSelector")const elDynamicBtn = evt.target; // Your dynamic element

评论

62赞 aces. 2/21/2013
这对我有用。有趣的是,上面的答案都没有指出必须使用非动态父选择器的事实。难怪“.on”之前对我不起作用。
4赞 Rich 4/7/2013
这个也对我有用,而上面的那些没有。 谢谢!
5赞 Rajshekar Reddy 1/6/2014
这是唯一对我有用的方法,因为我将事件绑定到动态元素而不是静态父元素。完美答案 。
5赞 Avatar 5/27/2014
$('#parent')这是我缺少的那个,它使 on() 的行为变得清晰,谢谢:)
1赞 spice 6/16/2018
这应该是最好的答案。缺少现有的父元素触摸让我有一段时间了。
3赞 user2257720 4/8/2013 #8

Jquery工作正常,但我在实现上述一些解决方案的渲染时遇到了一些问题。我使用 的问题是,它以某种方式呈现事件与方法不同。.on.on.hover

仅供参考,对于可能也有问题的其他人。我通过为动态添加的项目重新注册悬停事件来解决我的问题:

重新注册 Hover 事件,因为 Hover 不适用于动态创建的项。 因此,每次创建新/动态项目时,我都会再次添加悬停代码。完美工作

$('#someID div:last').hover(
    function() {
       //...
    },
    function() {
       //...
    }
);

评论

1赞 Liam 4/8/2013
hover是 和 事件 (api.jquery.com/mouseenter) 的包装器,而这些又是 的包装器。所以这在下面使用!所以我看不出这对使用 .在我看来,你在这里错过了别的东西。mouseentermouseleave.on('mouseenter', handler).on.on
3赞 Timbergus 5/6/2013 #9

我正在使用动态向它们添加新元素的表,并且在使用 on() 时,使其对我有用的唯一方法是使用非动态父级作为:

<table id="myTable">
    <tr>
        <td></td> // Dynamically created
        <td></td> // Dynamically created
        <td></td> // Dynamically created
    </tr>
</table>

<input id="myButton" type="button" value="Push me!">

<script>
    $('#myButton').click(function() {
        $('#myTable tr').append('<td></td>');
    });

    $('#myTable').on('click', 'td', function() {
        // Your amazing code here!
    });
</script>

这非常有用,因为要删除与 on() 绑定的事件,您可以使用 off(),而要使用一次事件,您可以使用 one()。

33赞 Abhishek 7/19/2013 #10

在 js 文件中添加此函数。 它将适用于每个浏览器

$(function() {
    $(document).on("click", '#mydiv', function() {
        alert("You have just clicked on ");
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='mydiv'>Div</div>

4赞 Nikolaus Pluta 7/25/2013 #11
$(.surrounding_div_class).on( 'click', '.test', function () {
alert( 'WORKS!' );
});

仅当类为 .surrounding_div_class 的 DIV 是对象 .test 的直接父级时才有效

如果 div 中有另一个对象将被填充,它将不起作用。

7赞 user3425150 3/17/2014 #12

我在jQuery的文档中找到了两个解决方案:

第一:在正文或文档上使用委托

例如:

 $("body").delegate('.test', 'click', function(){
 ...
  alert('test');
 });

为什么?

答:根据一组特定的根元素,将处理程序附加到与选择器匹配的所有元素的一个或多个事件,无论是现在还是将来。 友情链接: http://api.jquery.com/delegate/

第二:将 your 函数放在 “$( document )” 处,使用 “on” 并将其附加到要触发此函数的元素。 第一个参数是“事件处理程序”,第二个参数是元素,第三个参数是函数。 例如:

 $( document ).on( 'click', '.test', function () {
 ...
  alert('test');
 });

为什么?

答:事件处理程序仅绑定到当前选定的元素;在代码调用 .on() 时,它们必须存在于页面上。若要确保元素存在且可以选择,请在文档就绪处理程序中对页面上 HTML 标记中的元素执行事件绑定。如果要将新 HTML 注入到页面中,请在将新 HTML 放入页面后选择元素并附加事件处理程序。或者,使用委托事件附加事件处理程序,如下所述... 友情链接: https://api.jquery.com/on/

5赞 Nick Mitchell 10/23/2014 #13

另一种更简洁的替代方法(恕我直言)是使用原始 javascript 函数来响应单击事件,然后根据需要将目标元素传递回 jQuery。这种方法的优点是,您可以在任何位置动态添加元素,并且单击处理程序将“正常工作”,并且您无需担心将控制权委托给父元素等。

步骤1: 更新动态 html 以触发 onclick 事件。请务必将“event”对象作为参数传递

    $("button").click(function() {
        $("h2").html("<p class='test' onclick='test(event)'> click me </p>")
    });

步骤2: 创建测试函数以响应单击事件

    function test(e){
        alert();
    });

可选步骤3: 鉴于您使用的是jQuery,我假设获取对源按钮的引用会很有用

    function test(e){
        alert();

        // Get a reference to the button
        // An explanation of this line is available here
        var target = (e.target)? e.target : e.srcElement;

        // Pass the button reference to jQuery to do jQuery magic
        var $btn = $(target);

    });

3赞 Sasha Shepherd 1/7/2015 #14

我无法上线或委派在灯箱 (tinybox) 中处理 div。

我通过以下简单方法成功使用了 setTimelout:

$('#displayContact').click(function() {
    TINY.box.show({html:'<form><textarea id="contactText"></textarea><div id="contactSubmit">Submit</div></form>', close:true});
    setTimeout(setContactClick, 1000);
})

function setContactClick() {
    $('#contactSubmit').click(function() {
        alert($('#contactText').val());
    })
}
7赞 Jay Patel 2/12/2015 #15

使用委派对动态生成的内容应用事件的最佳方式。

$(document).on("eventname","selector",function(){
    // code goes here
});

所以你的代码现在是这样的

$(document).on("click",".test",function(){
    // code goes here
});
160赞 Prabhagaran 4/16/2015 #16

原因:

在 jQuery 中,Click() 事件直接绑定,仅当页面上存在特定元素(Html 代码)时(页面加载后),才会将事件处理程序附加到元素。

动态元素是在javascript或jquery(不是Html)的帮助下创建的。

它不会考虑在页面加载后创建的未来元素(动态)。

因此,正常的点击事件不会在动态元素上触发。

溶液:

为了克服这个问题,我们应该使用 on() 函数。on() 可以为当前和将来的元素委托事件。

委托事件的优点是可以将处理程序附加到将来添加到文档中的元素。

注意:delegate(),live() 和 on() 函数比 DOM 元素具有优势。从 JQuery 1.7 开始,delegate() 和 live() 已被弃用(不要使用它们)。

on() only 可以为当前和将来的元素委托事件。

所以,你的代码应该是这样的

$(document).ready 中删除代码:

$(".test").click(function(){

  alert();

});

更改为:

$(document).on('click','.test',function(){

  alert('Clicked');

});

评论

2赞 west44 6/30/2015
当父项不存在并且也在动态创建时,情况的出色答案。
6赞 Adam 7/12/2019
以上答案怎么可能没有提到最重要的那一行呢?这应该是经过检查的答案!感谢$(document).on('click','.test',function()
2赞 Daryl H 4/15/2016 #17

您可以在单击时添加动态创建的元素。示例如下。使用 When 来确保其完成。在我的示例中,我抓取了一个带有类扩展的 div,添加了一个“单击以查看更多”范围,然后使用该范围隐藏/显示原始 div。

$.when($(".expand").before("<span class='clickActivate'>Click to see more</span>")).then(function(){
    $(".clickActivate").click(function(){
        $(this).next().toggle();
    })
});
4赞 EliuX 11/11/2016 #18

如果您有一个指向某个容器或正文的二元链接:

var newLink= $("<a></a>", {
        "id": "approve-ctrl",
        "href": "#approve",
        "class": "status-ctrl",
        "data-attributes": "DATA"
    }).html("Its ok").appendTo(document.body);

您可以获取其原始 JavaScript 元素并向其添加事件侦听器,例如单击

newLink.get(0).addEventListener("click", doActionFunction);

无论您添加多少次这个新的链接实例,您都可以像使用 jquery 函数一样使用它。click

function doActionFunction(e) {
    e.preventDefault();
    e.stopPropagation();

    alert($(this).html());
}

因此,您将收到一条消息,上面写着

没关系

它比其他替代品具有更好的性能。

额外:您可以避免使用jquery并使用纯javascript来获得更好的性能。如果您使用的是 IE 版本8,则应使用此 polyfill 来使用该方法addEventListener

if (typeof Element.prototype.addEventListener === 'undefined') {
    Element.prototype.addEventListener = function (e, callback) {
      e = 'on' + e;
      return this.attachEvent(e, callback);
    };
  }
3赞 Daryn K. 11/17/2016 #19

您也可以使用 inside 元素onclick="do_something(this)"

0赞 Abhijit 6/1/2017 #20

使用“on”,因为单击会绑定到已经存在的元素。

例如

$('test').on('click',function(){
    alert('Test');
})

这将有所帮助。