【问题标题】:jQuery how to bind onclick event to dynamically added HTML element [duplicate]jQuery如何将onclick事件绑定到动态添加的HTML元素[重复]
【发布时间】:2010-12-04 06:48:14
【问题描述】:

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

但它从不运行绑定的函数。如果您能指出为什么这个示例不起作用以及如何让它正常运行,我会很高兴:

<!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>

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

【问题讨论】:

  • 当我在 FF 3.5 中测试时,您的示例页面运行良好
  • @Daff 不幸的是,你是对的!然后我显然已经提取了我的代码中实际工作的部分。感谢您指出这一点!
  • @Daff,我编辑了示例,因此它包含两个插入方法的位置。然后它真的停止工作:)

标签: javascript jquery bind


【解决方案1】:

所有这些方法都已弃用。您应该使用on 方法来解决您的问题。

如果你想定位一个动态添加的元素,你必须使用

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

这替换了已弃用的.live() 方法。

【讨论】:

  • *selector-to-your-element* 应该是 '.some-class''#some-id'
  • 我的问题是我正在做类似$('.row').on('click', function(){...}); 而不是$(document).on('click','.row',function(){...});
  • 请记住,$(document) 可以是页面上不会更改的任何元素。这可以防止过多的事件冒泡,加速你的 JS。例如。 $(document) -> $('.example-container')
  • @RickyBoyce 完美提示,谢谢。
【解决方案2】:

第一个问题是,当您在具有多个元素的 jQuery 集合上调用 append 时,会为每个元素创建要附加的元素的克隆,因此附加的事件观察器会丢失。

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

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

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

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

【讨论】:

  • 当您必须绑定对附加了其他功能的元素的点击时会出现问题。这就是为什么我建议使用 aM1Ne 答案。
  • 确实,当您针对由其他代码创建的已知标记结构时。但是在这里他自己插入元素,并且没有明确的选择器(它只是一个锚,可能有很多),所以他必须添加额外的标记才能定位元素。在这种情况下,将处理程序直接附加到元素同样容易,而不是捕获所有点击并测试选择器匹配。
  • 我理解你的回答,并不意味着它是错误的。当然,能够动态注入一些 html(比如加载了无限滚动的 ajax 的图片的 ul li)并且已经将按钮绑定到某些操作(比如灯箱),这会更舒服。
  • 这个答案对于默认情况下可以使用旧版本的 jQuery(例如 Drupal 7)的情况也非常有用。 on() 是在 jQuery 1.7 中引入的。
【解决方案3】:

Live 方法怎么样?

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

不过,您所做的看起来应该可行。 another post 看起来很相似。

【讨论】:

  • 你说得对,它确实有效。我的错。所以我编辑了这个问题。
  • 是的,这类问题正是直播活动要解决的问题。
  • 该问题与直播活动无关,但在这种情况下,直播活动可以解决问题。 Daff 提供的答案也解决了这个问题,并且没有在方程式中添加直播事件的新概念
  • live() 现在已弃用,取而代之的是 on() link
  • live() 在 jQuery 1.9 中被on() 取代
【解决方案4】:

聚会有点晚了,但我想我会尝试澄清一些关于 jQuery 事件处理程序的常见误解。从 jQuery 1.7 开始,应使用 .on() 代替已弃用的 .live(),将事件处理程序委托给在分配事件处理程序后的任何时候动态创建的元素。

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

新方法(示例1):

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

});

不推荐使用的方法(示例 2):

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

});

如上图,有区别。扭曲的是 .on() 实际上可以调用类似于 .live(),通过将选择器传递给 jQuery 函数本身:

示例 3:

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

});

但是,如果不使用示例 1 中的 $(document),示例 3 将不适用于动态创建的元素。如果您不需要动态委托,示例 3 绝对可以。

$(document).on() 应该用于所有内容吗?

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

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

不一定。以下只是示例 3 的快捷方式:

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

});

以上内容完全有效,因此在不需要动态委托时使用哪种方法实际上是个人喜好问题。

参考资料:

【讨论】:

    【解决方案5】:

    考虑一下:

    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...
            });
          });
    });
    

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

    按照建议,最好的方法可能是通过 live 方法将其绑定到特定的类。

    【讨论】:

    • 感谢您的回答,达夫。我只能将事件侦听器添加到 DOM 中的元素是不可能的。但是,我现在将更改我的代码来做到这一点。 (应该没问题,因为我只是为添加的链接添加了特殊的 css 类)。
    • 是的,你是对的,它不是 DOM(它实际上与单个 DOM 一起工作),抱歉。但我也发现,绑定到动态创建的元素似乎很烦人,只要它们不能被不同的 jQuery 选择器选择。
    • “来自 BOUND 函数调用的问候。”抱歉,这篇文章(整页;问题和答案)上的内容太多了,我只是想帮忙,你知道的,澄清一下。
    【解决方案6】:

    与元素一起创建单击事件是可能的,有时是必要的。例如,当基于选择器的绑定不是一个选项时。关键部分是通过在单个元素上使用.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>
    

    【讨论】:

      【解决方案7】:
          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);
                  });
              });
          }
      

      【讨论】:

        【解决方案8】:

        我相信这样做的好方法:

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

        【讨论】:

        • 我不能使用#id 添加到元素,因为我想对许多元素执行此操作。查看更新的代码示例:)
        【解决方案9】:
        <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>
        

        【讨论】:

          猜你喜欢
          • 2014-09-17
          • 1970-01-01
          • 2011-09-18
          • 2019-11-13
          • 1970-01-01
          • 1970-01-01
          • 2015-09-07
          • 1970-01-01
          • 2011-08-11
          相关资源
          最近更新 更多