jQuery如何将onclick事件绑定到动态添加的HTML元素

时间:2022-08-26 10:32:01

I want to bind an onclick event to an element I insert dynamically with jQuery

我想将onclick事件绑定到用jQuery动态插入的元素上

But It never runs the binded function. I'd be happy if you can point out why this example is not working and how I can get it to run properly:

但它从不运行绑定函数。如果你能指出这个例子为什么不奏效,以及我如何让它正常运行,我会很高兴:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"        
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="da" lang="da">
        <head>
          <title>test of click binding</title>

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
          <script type="text/javascript">


        jQuery(function(){
          close_link = $('<a class="" href="#">Click here to see an alert</a>');
          close_link.bind("click", function(){
            alert('hello from binded function call');
            //do stuff here...
          });
  
          $('.add_to_this').append(close_link);
        });
          </script>
        </head>
        <body>
          <h1 >Test of click binding</h1>
          <p>problem: to bind a click event to an element I append via JQuery.</p>

          <div class="add_to_this">
            <p>The link is created, then added here below:</p>
          </div>

          <div class="add_to_this">
            <p>Another is added here below:</p>
          </div>


        </body>
        </html>

EDIT: I edited the example to contain two elements the method is inserted to. In that case, the alert() call is never executed. (thanks to @Daff for pointing that out in a comment)

编辑:我编辑了示例,以包含插入方法的两个元素。在这种情况下,不会执行alert()调用。(感谢@Daff在评论中指出这一点)

9 个解决方案

#1


57  

The first problem is that when you call append on a jQuery set with more than one element, a clone of the element to append is created for each and thus the attached event observer is lost.

第一个问题是,当您调用带有多个元素的jQuery集上的append时,将为每个元素创建一个元素的克隆,从而丢失所附加的事件观察者。

An alternative way to do it would be to create the link for each element:

另一种方法是为每个元素创建链接:

function handler() { alert('hello'); }
$('.add_to_this').append(function() {
  return $('<a>Click here</a>').click(handler);
})

Another potential problem might be that the event observer is attached before the element has been added to the DOM. I'm not sure if this has anything to say, but I think the behavior might be considered undetermined. A more solid approach would probably be:

另一个潜在的问题可能是在元素添加到DOM之前附加了事件观察者。我不确定这是否有什么可说的,但我认为这种行为可能被认为是不确定的。更可靠的办法可能是:

function handler() { alert('hello'); }
$('.add_to_this').each(function() {
  var link = $('<a>Click here</a>');
  $(this).append(link);
  link.click(handler);
});

#2


265  

All of these methods are deprecated. You should use the on method to solve your problem.

所有这些方法都被弃用。你应该用on方法来解决你的问题。

If you want to target a dynamically added element you'll have to use

如果您想针对一个动态添加的元素,您将不得不使用它

$(document).on('click', selector-to-your-element , function() {
     //code here ....
});

this replace the deprecated .live() method.

这将替换已废弃的.live()方法。

#3


51  

How about the Live method?

现场直播怎么样?

$('.add_to_this a').live('click', function() {
    alert('hello from binded function call');
});

Still, what you did about looks like it should work. There's another post that looks pretty similar.

尽管如此,你所做的看起来应该是可行的。还有一篇文章看起来很相似。

#4


18  

A little late to the party but I thought I would try to clear up some common misconceptions in jQuery event handlers. As of jQuery 1.7, .on() should be used instead of the deprecated .live(), to delegate event handlers to elements that are dynamically created at any point after the event handler is assigned.

参加聚会有点晚,但我想我应该试着澄清jQuery事件处理程序中一些常见的误解。在jQuery 1.7中,应该使用.on()来代替已弃用的.live(),将事件处理程序委托给在事件处理程序分配后的任何时刻动态创建的元素。

That said, it is not a simple of switching live for on because the syntax is slightly different:

也就是说,切换到live on并不简单,因为语法略有不同:

New method (example 1):

新方法(示例1):

$(document).on('click', '#someting', function(){

});

Deprecated method (example 2):

不赞成使用的方法(例2):

$('#something').live(function(){

});

As shown above, there is a difference. The twist is .on() can actually be called similar to .live(), by passing the selector to the jQuery function itself:

如上所示,这是有区别的。通过将选择器传递给jQuery函数本身,可以将其称为.on()。

Example 3:

示例3:

$('#something').on('click', function(){

});

However, without using $(document) as in example 1, example 3 will not work for dynamically created elements. The example 3 is absolutely fine if you don't need the dynamic delegation.

但是,如果不使用$(文档),例如1,示例3将不能用于动态创建的元素。如果不需要动态委托,示例3绝对没问题。

Should $(document).on() be used for everything?

是否应该将$(document).on()用于所有内容?

It will work but if you don't need the dynamic delegation, it would be more appropriate to use example 3 because example 1 requires slightly more work from the browser. There won't be any real impact on performance but it makes sense to use the most appropriate method for your use.

它可以工作,但是如果您不需要动态委托,那么使用示例3会更合适,因为示例1需要浏览器做更多的工作。不会对性能产生真正的影响,但是使用最合适的方法是有意义的。

Should .on() be used instead of .click() if no dynamic delegation is needed?

如果不需要动态委托,应该使用.on()而不是.click()吗?

Not necessarily. The following is just a shortcut for example 3:

不一定。下面只是一个例子3的捷径:

$('#something').click(function(){

});

The above is perfectly valid and so it's really a matter of personal preference as to which method is used when no dynamic delegation is required.

上述方法是完全有效的,所以当不需要动态委托时,使用哪种方法实际上是个人偏好的问题。

References:

引用:

#5


1  

Consider this:

考虑一下:

jQuery(function(){
  var close_link = $('<a class="" href="#">Click here to see an alert</a>');
      $('.add_to_this').append(close_link);
      $('.add_to_this').children().each(function()
      {
        $(this).click(function() {
            alert('hello from binded function call');
            //do stuff here...
        });
      });
});

It will work because you attach it to every specific element. This is why you need - after adding your link to the DOM - to find a way to explicitly select your added element as a JQuery element in the DOM and bind the click event to it.

它会起作用,因为您将它附加到每个特定的元素。这就是为什么您需要——在向DOM添加链接之后——找到一种方法来显式地选择添加的元素作为DOM中的JQuery元素并将单击事件绑定到它。

The best way will probably be - as suggested - to bind it to a specific class via the live method.

最好的方法可能是——如建议的那样——通过live方法将它绑定到特定的类。

#6


0  

I believe the good way it to do:

我相信这样做的好处:

$('#id').append('<a id="#subid" href="#">...</a>');
$('#subid').click( close_link );

#7


0  

It is possible and sometimes necessary to create the click event along with the element. This is for example when selector based binding is not an option. The key part is to avoid the problem that Tobias was talking about by using .replaceWith() on a single element. Note that this is just a proof of concept.

创建单击事件和元素是可能的,有时也是必要的。例如,当基于选择器的绑定不是选项时。关键部分是通过在单个元素上使用. replacewith()避免Tobias所讨论的问题。注意,这只是概念的证明。

<script>
    // This simulates the object to handle
    var staticObj = [
        { ID: '1', Name: 'Foo' },
        { ID: '2', Name: 'Foo' },
        { ID: '3', Name: 'Foo' }
    ];
    staticObj[1].children = [
        { ID: 'a', Name: 'Bar' },
        { ID: 'b', Name: 'Bar' },
        { ID: 'c', Name: 'Bar' }
    ];
    staticObj[1].children[1].children = [
        { ID: 'x', Name: 'Baz' },
        { ID: 'y', Name: 'Baz' }
    ];

    // This is the object-to-html-element function handler with recursion
    var handleItem = function( item ) {
        var ul, li = $("<li>" + item.ID + " " + item.Name + "</li>");

        if(typeof item.children !== 'undefined') {
            ul = $("<ul />");
            for (var i = 0; i < item.children.length; i++) {
                ul.append(handleItem(item.children[i]));
            }
            li.append(ul);
        }

        // This click handler actually does work
        li.click(function(e) {
            alert(item.Name);
            e.stopPropagation();
        });
        return li;
    };

    // Wait for the dom instead of an ajax call or whatever
    $(function() {
        var ul = $("<ul />");

        for (var i = 0; i < staticObj.length; i++) {
            ul.append(handleItem(staticObj[i]));
        }

        // Here; this works.
        $('#something').replaceWith(ul);
    });
</script>
<div id="something">Magical ponies ♥</div>

#8


0  

    function load_tpl(selected=""){
        $("#load_tpl").empty();
        for(x in ds_tpl){
            $("#load_tpl").append('<li><a id="'+ds_tpl[x]+'" href="#" >'+ds_tpl[x]+'</a></li>');
        }
        $.each($("#load_tpl a"),function(){
            $(this).on("click",function(e){
                alert(e.target.id);
            });
        });
    }

#9


-2  

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>    
<script>
    $(document).ready(function(){
        $(document).on('click', '.close', function(){
            var rowid='row'+this.id;
            var sl = '#tblData tr[id='+rowid+']';
            console.log(sl);
            $(sl).remove();
        });
        $("#addrow").click(function(){
            var row='';
            for(var i=0;i<10;i++){
                row=i;
                row='<tr id=row'+i+'>'
                    +   '<td>'+i+'</td>'
                    +   '<td>ID'+i+'</td>'
                    +   '<td>NAME'+i+'</td>'
                    +   '<td><input class=close type=button id='+i+' value=X></td>'
                    +'</tr>';
                console.log(row);
                $('#tblData tr:last').after(row);
            }
        });
    });

</script>
</head>
  <body>
    <br/><input type="button" id="addrow" value="Create Table"/>
    <table id="tblData" border="1" width="40%">
        <thead>
        <tr>
            <th>Sr</th>
            <th>ID</th>
            <th>Name</th>
            <th>Delete</th>
        </tr>
        </thead>
    </table>
    </body>
 </html>

#1


57  

The first problem is that when you call append on a jQuery set with more than one element, a clone of the element to append is created for each and thus the attached event observer is lost.

第一个问题是,当您调用带有多个元素的jQuery集上的append时,将为每个元素创建一个元素的克隆,从而丢失所附加的事件观察者。

An alternative way to do it would be to create the link for each element:

另一种方法是为每个元素创建链接:

function handler() { alert('hello'); }
$('.add_to_this').append(function() {
  return $('<a>Click here</a>').click(handler);
})

Another potential problem might be that the event observer is attached before the element has been added to the DOM. I'm not sure if this has anything to say, but I think the behavior might be considered undetermined. A more solid approach would probably be:

另一个潜在的问题可能是在元素添加到DOM之前附加了事件观察者。我不确定这是否有什么可说的,但我认为这种行为可能被认为是不确定的。更可靠的办法可能是:

function handler() { alert('hello'); }
$('.add_to_this').each(function() {
  var link = $('<a>Click here</a>');
  $(this).append(link);
  link.click(handler);
});

#2


265  

All of these methods are deprecated. You should use the on method to solve your problem.

所有这些方法都被弃用。你应该用on方法来解决你的问题。

If you want to target a dynamically added element you'll have to use

如果您想针对一个动态添加的元素,您将不得不使用它

$(document).on('click', selector-to-your-element , function() {
     //code here ....
});

this replace the deprecated .live() method.

这将替换已废弃的.live()方法。

#3


51  

How about the Live method?

现场直播怎么样?

$('.add_to_this a').live('click', function() {
    alert('hello from binded function call');
});

Still, what you did about looks like it should work. There's another post that looks pretty similar.

尽管如此,你所做的看起来应该是可行的。还有一篇文章看起来很相似。

#4


18  

A little late to the party but I thought I would try to clear up some common misconceptions in jQuery event handlers. As of jQuery 1.7, .on() should be used instead of the deprecated .live(), to delegate event handlers to elements that are dynamically created at any point after the event handler is assigned.

参加聚会有点晚,但我想我应该试着澄清jQuery事件处理程序中一些常见的误解。在jQuery 1.7中,应该使用.on()来代替已弃用的.live(),将事件处理程序委托给在事件处理程序分配后的任何时刻动态创建的元素。

That said, it is not a simple of switching live for on because the syntax is slightly different:

也就是说,切换到live on并不简单,因为语法略有不同:

New method (example 1):

新方法(示例1):

$(document).on('click', '#someting', function(){

});

Deprecated method (example 2):

不赞成使用的方法(例2):

$('#something').live(function(){

});

As shown above, there is a difference. The twist is .on() can actually be called similar to .live(), by passing the selector to the jQuery function itself:

如上所示,这是有区别的。通过将选择器传递给jQuery函数本身,可以将其称为.on()。

Example 3:

示例3:

$('#something').on('click', function(){

});

However, without using $(document) as in example 1, example 3 will not work for dynamically created elements. The example 3 is absolutely fine if you don't need the dynamic delegation.

但是,如果不使用$(文档),例如1,示例3将不能用于动态创建的元素。如果不需要动态委托,示例3绝对没问题。

Should $(document).on() be used for everything?

是否应该将$(document).on()用于所有内容?

It will work but if you don't need the dynamic delegation, it would be more appropriate to use example 3 because example 1 requires slightly more work from the browser. There won't be any real impact on performance but it makes sense to use the most appropriate method for your use.

它可以工作,但是如果您不需要动态委托,那么使用示例3会更合适,因为示例1需要浏览器做更多的工作。不会对性能产生真正的影响,但是使用最合适的方法是有意义的。

Should .on() be used instead of .click() if no dynamic delegation is needed?

如果不需要动态委托,应该使用.on()而不是.click()吗?

Not necessarily. The following is just a shortcut for example 3:

不一定。下面只是一个例子3的捷径:

$('#something').click(function(){

});

The above is perfectly valid and so it's really a matter of personal preference as to which method is used when no dynamic delegation is required.

上述方法是完全有效的,所以当不需要动态委托时,使用哪种方法实际上是个人偏好的问题。

References:

引用:

#5


1  

Consider this:

考虑一下:

jQuery(function(){
  var close_link = $('<a class="" href="#">Click here to see an alert</a>');
      $('.add_to_this').append(close_link);
      $('.add_to_this').children().each(function()
      {
        $(this).click(function() {
            alert('hello from binded function call');
            //do stuff here...
        });
      });
});

It will work because you attach it to every specific element. This is why you need - after adding your link to the DOM - to find a way to explicitly select your added element as a JQuery element in the DOM and bind the click event to it.

它会起作用,因为您将它附加到每个特定的元素。这就是为什么您需要——在向DOM添加链接之后——找到一种方法来显式地选择添加的元素作为DOM中的JQuery元素并将单击事件绑定到它。

The best way will probably be - as suggested - to bind it to a specific class via the live method.

最好的方法可能是——如建议的那样——通过live方法将它绑定到特定的类。

#6


0  

I believe the good way it to do:

我相信这样做的好处:

$('#id').append('<a id="#subid" href="#">...</a>');
$('#subid').click( close_link );

#7


0  

It is possible and sometimes necessary to create the click event along with the element. This is for example when selector based binding is not an option. The key part is to avoid the problem that Tobias was talking about by using .replaceWith() on a single element. Note that this is just a proof of concept.

创建单击事件和元素是可能的,有时也是必要的。例如,当基于选择器的绑定不是选项时。关键部分是通过在单个元素上使用. replacewith()避免Tobias所讨论的问题。注意,这只是概念的证明。

<script>
    // This simulates the object to handle
    var staticObj = [
        { ID: '1', Name: 'Foo' },
        { ID: '2', Name: 'Foo' },
        { ID: '3', Name: 'Foo' }
    ];
    staticObj[1].children = [
        { ID: 'a', Name: 'Bar' },
        { ID: 'b', Name: 'Bar' },
        { ID: 'c', Name: 'Bar' }
    ];
    staticObj[1].children[1].children = [
        { ID: 'x', Name: 'Baz' },
        { ID: 'y', Name: 'Baz' }
    ];

    // This is the object-to-html-element function handler with recursion
    var handleItem = function( item ) {
        var ul, li = $("<li>" + item.ID + " " + item.Name + "</li>");

        if(typeof item.children !== 'undefined') {
            ul = $("<ul />");
            for (var i = 0; i < item.children.length; i++) {
                ul.append(handleItem(item.children[i]));
            }
            li.append(ul);
        }

        // This click handler actually does work
        li.click(function(e) {
            alert(item.Name);
            e.stopPropagation();
        });
        return li;
    };

    // Wait for the dom instead of an ajax call or whatever
    $(function() {
        var ul = $("<ul />");

        for (var i = 0; i < staticObj.length; i++) {
            ul.append(handleItem(staticObj[i]));
        }

        // Here; this works.
        $('#something').replaceWith(ul);
    });
</script>
<div id="something">Magical ponies ♥</div>

#8


0  

    function load_tpl(selected=""){
        $("#load_tpl").empty();
        for(x in ds_tpl){
            $("#load_tpl").append('<li><a id="'+ds_tpl[x]+'" href="#" >'+ds_tpl[x]+'</a></li>');
        }
        $.each($("#load_tpl a"),function(){
            $(this).on("click",function(e){
                alert(e.target.id);
            });
        });
    }

#9


-2  

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>    
<script>
    $(document).ready(function(){
        $(document).on('click', '.close', function(){
            var rowid='row'+this.id;
            var sl = '#tblData tr[id='+rowid+']';
            console.log(sl);
            $(sl).remove();
        });
        $("#addrow").click(function(){
            var row='';
            for(var i=0;i<10;i++){
                row=i;
                row='<tr id=row'+i+'>'
                    +   '<td>'+i+'</td>'
                    +   '<td>ID'+i+'</td>'
                    +   '<td>NAME'+i+'</td>'
                    +   '<td><input class=close type=button id='+i+' value=X></td>'
                    +'</tr>';
                console.log(row);
                $('#tblData tr:last').after(row);
            }
        });
    });

</script>
</head>
  <body>
    <br/><input type="button" id="addrow" value="Create Table"/>
    <table id="tblData" border="1" width="40%">
        <thead>
        <tr>
            <th>Sr</th>
            <th>ID</th>
            <th>Name</th>
            <th>Delete</th>
        </tr>
        </thead>
    </table>
    </body>
 </html>