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

时间:2011-07-12 02:02:23

标签: jquery events

<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关联的点击事件。但事件不起作用。

有人可以帮忙吗?

20 个答案:

答案 0 :(得分:645)

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

  

委托事件的优势在于它们可以处理来自稍后添加到文档的后代元素的事件。

Source

以下是您要找的内容:

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!');
});

为我工作。 Tried it与jsFiddle。

或者用delegate()

进行新的方式
$("h2").delegate("p", "click", function(){
    alert('you clicked me again!');
});

An updated jsFiddle

答案 1 :(得分:204)

使用.on() method with delegated events

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

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

P.S:不要使用.live()!从jQuery 1.7+开始,不推荐使用.live()方法。

答案 2 :(得分:88)

原因:

在jQuery中,Click() - 仅在html代码中已存在该元素时才附加事件处理程序。

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

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

因此点击事件不会触发。

解决方案:

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

delegate(),live() on()函数优于DOM元素。

上的

可以触发现有元素以及未来元素。

上的

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

不推荐使用

delegate(),live()函数(不要使用这些函数)。

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

从$(document).ready:

中删除代码
$(".test").click(function(){

  alert();

});

转变为:

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

  alert('Clicked');

});

答案 3 :(得分:19)

在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 :(得分:12)

更改

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

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

LIVE DEMO

jQuery .live()

答案 5 :(得分:11)

您需要使用.live来实现此目的:

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

或者如果你使用jquery 1.7+使用.on

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

答案 6 :(得分:7)

尝试.live().delegate()

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

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

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

更多信息:

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

答案 7 :(得分:6)

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

首先:在正文或文档上使用委托

例如:

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

为什么?

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

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

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

为什么?

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

答案 8 :(得分:5)

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

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

所以你的代码现在就像这样

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

答案 9 :(得分:4)

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

仅当具有类.surrounding_div_class的DIV是对象的直接父级时才会起作用.test

如果div中有另一个对象将被填充,它将无法正常工作。

答案 10 :(得分:4)

您遇到的问题是,在DOM中存在任何带有“test”类的内容之前,您尝试将“test”类绑定到该事件。虽然看起来这似乎都是动态的,但真正发生的是JQueryDOM进行了传递,并在ready()函数触发时将点击事件连接起来,这发生在你之前在您的按钮事件中创建了“Click Me”。

通过将“test”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>

使用live()(正如其他人指出的那样)是另一种方法,但我觉得指出JS代码中的小错误也是一个好主意。你所写的并没有错,只需要正确确定范围。掌握DOM和JS的工作方式对于许多传统开发人员而言是最棘手的事情之一。

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

答案 11 :(得分:3)

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

对于可能也有问题的其他人来说,只是fyi。我通过重新注册动态添加项目的悬停事件来解决我的问题:

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

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

答案 12 :(得分:3)

另一个更简洁的替代方案(IMHO)是使用原始javascript函数响应on click事件,然后将目标元素传递回jQuery(如果您愿意)。这种方法的优点是,您可以在任何地方动态添加元素,点击处理程序将只是工作,您无需担心将控制权委托给父元素,等等。

第1步:更新动态html以触发onclick事件。一定要通过&#39;事件&#39;对象作为参数


    $("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);

    });

答案 13 :(得分:3)

我无法上传或委托在灯箱(tinybox)中使用div。

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

$('#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());
    })
}

答案 14 :(得分:3)

.live功能很棒。

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

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

干杯, ANKIT。

答案 15 :(得分:3)

如果您在某个容器或身体上添加了一个dinamically链接:

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。如果您使用的是最高版本8的IE,则应使用此polyfill来使用方法addEventListener

if (typeof Element.prototype.addEventListener === 'undefined') {
    Element.prototype.addEventListener = function (e, callback) {
      e = 'on' + e;
      return this.attachEvent(e, callback);
    };
  }

答案 16 :(得分:3)

您也可以在元素

中使用onclick="do_something(this)"

答案 17 :(得分:2)

我正在使用表格动态添加新元素,当使用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()

答案 18 :(得分:2)

您可以添加点击动态创建的元素。以下示例。使用When确保完成。在我的例子中,我在类扩展时抓取一个div,添加一个&#34;点击查看更多&#34; span,然后使用该跨度隐藏/显示原始div。

listView1.SelectedItems.Count > 0

答案 19 :(得分:0)

使用'on',因为click会绑定到已存在的元素。

例如

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

这会有所帮助。