关于jquery:Click事件不适用于动态生成的元素

Click event doesn't work on dynamically generated elements

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<head>
    <script type="text/javascript" src="jquery.js">
    <script type="text/javascript">

        $(document).ready(function() {

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

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

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

我试图通过单击按钮,在中生成一个新的类名为test的标记。我还定义了一个与test关联的点击事件。但是这个活动不起作用。

有人能帮忙吗?


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

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.

来源

以下是您要查找的内容:

1
2
3
4
5
6
7
8
9
10
11
12
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());
});
1
2
3
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">

<button>generate new element</button>

以上内容适用于使用jquery 1.7+版本的用户。如果您使用的是旧版本,请参阅下面以前的答案。

上一个答案:

尝试使用live()

1
2
3
4
5
6
7
8
9
$("button").click(function(){
    $("h2").html("<p class='test'>click me
</p>")
});  


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

为我工作。用jsiddle试试看。

或者有一种新的方法来处理delegate()

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

更新的jsiddle。


对委托事件使用.on()方法

1
2
3
$('#staticParent').on('click', '.dynamicElement', function() {
    // Do something on an existent or future .dynamicElement
});

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

p.s:不要使用.live()!从jquery 1.7+开始,.live()方法被弃用。


原因:

在jquery中,click()-仅当HTML代码中已经存在元素时才附加事件处理程序。

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

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

所以点击事件不会触发。

解决方案:

为了克服这个问题,我们应该使用on()函数。

与DOM元素相比,delegate()、live()和on()函数具有优势。

on可以触发现有元素和未来元素。

上可以考虑在整个页面中都存在的元素。

delegate()、live()函数已弃用(不要使用这些函数)。

您应该使用on函数在动态创建的(将来的)元素上触发事件。

从$(document)中删除代码。就绪:

1
2
3
4
5
$(".test").click(function(){

  alert();

});

变为:

1
2
3
4
5
$(document).on('click','.test',function(){

  alert('Clicked');

});


在JS文件中添加此函数。它将在每个浏览器上工作

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


变化

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

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

现场演示

jquery .live()


你需要使用。活下来工作:

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

或者如果您正在使用jquery 1.7+use.on:

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


试试.live().delegate()

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

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

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

更多信息:

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


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

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

例如:

1
2
3
4
 $("body").delegate('.test', 'click', function(){
 ...
  ;
 });

为什么?

答:根据一组特定的根元素,将一个处理程序附加到一个或多个事件中,用于当前或将来匹配选择器的所有元素。链接:http://api.jquery.com/delegate/

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

1
2
3
4
 $( document ).on( 'click', '.test', function () {
 ...
  ;
 });

为什么?

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


使用委派在动态生成的内容上应用事件的最佳方法。

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

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

1
2
3
$(document).on("click",".test",function(){
    // code goes here
});


问题是,在DOM中没有任何"test"类之前,您试图将"test"类绑定到事件。虽然看起来这一切都是动态的,但实际发生的是JQueryDOM上进行传递,并在ready()函数启动时连接click事件,这发生在您在按钮事件中创建"click me"之前。

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

1
2
3
4
5
6
7
8
9
10
<script type="text/javascript">
    $(document).ready(function(){                          
        $("button").click(function(){                                  
            $("h2").html("<p class='test'>click me
</p>")                          
            $(".test").click(function(){                          
                alert()                          
            });      
        });                                    
    });

使用live()(正如其他人指出的)是另一种方法,但我认为指出JS代码中的小错误也是一个好主意。你写的东西没有错,只是需要正确的范围。掌握DOM和JS的工作原理是许多传统开发人员难以理解的事情之一。

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


1
2
3
$(.surrounding_div_class).on( 'click', '.test', function () {
alert( 'WORKS!' );
});

仅当带有class.enounding摲div_类的DIV是对象的直接父级时才有效。test

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


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

给其他可能也有问题的人打电话。我通过重新注册动态添加项的悬停事件解决了我的问题:

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

1
2
3
4
5
6
7
8
$('#someID div:last').hover(
    function() {
       //...
    },
    function() {
       //...
    }
);


另一种更简洁的替代方法(imho)是使用一个原始的javascript函数来响应单击事件,然后根据需要将目标元素返回jquery。这种方法的优点是,您可以在任何地方动态添加元素,而单击处理程序将"正常工作",您不必担心将控制权委托给父元素,等等。

步骤1:更新动态HTML以触发onclick事件。确保将"event"对象作为参数传递

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

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

1
2
3
    function test(e){
        alert();
    });

可选步骤3:假设您正在使用jquery,我假设它将有助于获取对源按钮的引用。

1
2
3
4
5
6
7
8
9
10
11
    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);

    });

活功能很好。

它用于动态地将元素添加到阶段。

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

干杯,Ankit。


我不能让现场或代表在一个灯箱(Tinybox)的分区工作。

我成功地使用了setTimeout,方法如下:

1
2
3
4
5
6
7
8
9
10
$('#displayContact').click(function() {
    TINY.box.show({html:'<form><textarea id="contactText"></textarea>Submit</form>', close:true});
    setTimeout(setContactClick, 1000);
})

function setContactClick() {
    $('#contactSubmit').click(function() {
        alert($('#contactText').val());
    })
}

如果您有一个常规添加到某个容器或主体的链接:

1
2
3
4
5
6
var newLink= $("", {
       "id":"approve-ctrl",
       "href":"#approve",
       "class":"status-ctrl",
       "data-attributes":"DATA"
    }).html("Its ok").appendTo(document.body);

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

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

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

1
2
3
4
5
6
function doActionFunction(e) {
    e.preventDefault();
    e.stopPropagation();

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

所以你会收到一条消息说

Its ok

它的性能比其他替代方案要好。

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

1
2
3
4
5
6
if (typeof Element.prototype.addEventListener === 'undefined') {
    Element.prototype.addEventListener = function (e, callback) {
      e = 'on' + e;
      return this.attachEvent(e, callback);
    };
  }

也可以使用onclick="do_something(this)"内部元素


您可以单击添加动态创建的元素。下面的例子。使用"何时"来确保完成。在我的示例中,我用类展开来抓取一个DIV,添加一个"单击以查看更多信息"范围,然后使用该范围隐藏/显示原始的DIV。

1
2
3
4
5
$.when($(".expand").before("<span class='clickActivate'>Click to see more</span>")).then(function(){
    $(".clickActivate").click(function(){
        $(this).next().toggle();
    })
});

我使用的是动态添加新元素的表,当使用on()时,使其对我有效的唯一方法是将非动态父级用作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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!">


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

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

这真的很有用,因为要删除用on()绑定的事件,可以使用off(),并且要使用事件一次,可以使用一个()。


使用"on"作为click get绑定到已经存在的元素。

例如

1
2
3
$('test').on('click',function(){
    ;
})

这会有帮助的。