【问题标题】:Objects added dynamically to the DOM don't respond to jQuery Events动态添加到 DOM 的对象不响应 jQuery 事件
【发布时间】:2014-01-13 19:52:10
【问题描述】:

我有一个表格,我正在动态添加行,每一行都有 2 个单元格,其中一个将包含一个输入字段,我计划在其中使用 DatePicker UI 来选择一个日期。当我添加新行时出现问题,单元格和所有内容都添加得很好,但是当我单击输入字段时不知何故不显示 DatePicker。阅读周围我了解到我应该使用“事件委托”,因为新元素从一开始就没有加载。但是对于我的一生,我一直无法理解如何去做,如果有人能指出我正确的方向,那就太好了。谢谢

到目前为止我得到的代码:

<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-    ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(document).ready(function() {
  $( ".datepicker" ).datepicker();
  $( "#TheTable" ).on("change",".datepicker",function(){
    $( this ).datepicker( "option", "dateFormat", "yy-mm-dd" );
  });
});

function addRow() {   
    var table = document.getElementById("TheTable");
    var row = table.insertRow(-1);
    var cell1 = row.insertCell(0);
    var cell2 = row.insertCell(1);
    cell1.innerHTML='Date';
    cell2.innerHTML='<input type="text" class="datepicker"/>';
}
</script>
</head>
<body>
<table name="MyTable" id="TheTable">
  <tr>
    <td>Date</td>
    <td><input type="text" class="datepicker" /></td>
  </tr>
  <tr>
  <td>Date</td>
    <td><input type="text" class="datepicker" /></td>
  </tr>
</table>
<input type="button" onClick="return addRow()" value ="Add Another Date">   
</body>
</html>

【问题讨论】:

    标签: javascript jquery event-delegation


    【解决方案1】:
    $( "#TheTable" ).on("change",".datepicker",function() {
    

    这应该可行。

    .on() 通过侦听 父元素 来处理冒泡的事件(see here for explanation of bubbling - 第一段),以便新元素触发的事件冒泡到正在侦听的父元素到。

    作为旁注,我想提一下,最好听听所需元素的最低公共父级,否则 jQuery 将评估不必要的事件。

    jQuery docs for .on()

    以下是.on() 文档的要点:

    .on( events [, selector ] [, data ], handler(eventObject) )

    大多数浏览器事件冒泡或传播,从文档中最深、最里面的元素(事件目标)一直到正文和 document 元素.在 Internet Explorer 8 及更低版本中,changesubmit 等一些事件本身不会冒泡,但 jQuery 将这些事件修补为冒泡并创建一致的跨浏览器行为。

    如果selector 被省略或为空,则事件处理程序被称为直接直接绑定。每次在所选元素上发生事件时都会调用处理程序,无论是从后代(内部)元素的元素或气泡直接发生。

    当提供selector 时,事件处理程序被称为委托。当事件直接发生在绑定元素上时,不会调用处理程序,而只会调用与选择器匹配的后代(内部元素)。 jQuery 将事件从事件目标冒泡到附加处理程序的元素(即从最内到最外的元素),并为匹配选择器的路径上的任何元素运行处理程序。

    事件处理程序仅绑定到当前选定的元素;在您的代码调用 .on()

    时,它们必须存在于页面上

    【讨论】:

    • 如果我在提供selector 时理解正确,则该事件是委托的,这意味着该事件发生在共享选择器的元素的后代中。根据文档,我有两个选择;我要么选择元素并在新 HTML 之后附加事件处理程序,要么使用委托事件。您提供的代码就是这样做的,它使用委托事件来附加事件处理程序。我对么?我实施了你的解决方案,但我无法让它工作。我将代码更新为我现在所拥有的。我什至不知道我做错了什么...感谢您的帮助。
    • 是的,你理解正确。您可以在添加时将侦听器附加到元素 - 在您的 addRow() 函数中,但这样做您添加了额外的事件侦听器;只有一个听起来更好,不是吗? ;P 如果您打算这样做,请记住在删除行时删除侦听器!您的代码现在看起来很到位,如果没有看到更多,我无法提出更多建议。你能把我链接到实时版本吗?
    • 啊 - 我发现了你的错误!您必须在新元素上初始化日期选择器才能工作。我将它全部粘贴到jsFiddle 中以便调试它,看看我添加到addRow() 的最后一行。 jsfiddle.net/FAcF2
    • 非常感谢,它现在完美运行。我有点想我需要在新元素上初始化日期选择器以使其工作,因此我之前的评论询问如何做到这一点......但我自己无法弄清楚。再次,非常感谢。编码愉快!
    • 如果我错了,请纠正我。您是否正在使用.not() 选择不属于 .datepicker 类的元素,然后将它们添加到其中?
    【解决方案2】:

    您需要倾听父级的声音才能定位动态绘制的内容。替换:

    $(document).ready(function() {
      $( ".datepicker" ).datepicker();
      $( ".datepicker" ).on("change",function() {
        $( ".datepicker" ).datepicker( "option", "dateFormat", "yy-mm-dd" );
      });
    });
    

    与:

    $(document).ready(function() {
      $( ".datepicker" ).datepicker();
      $( '#TheTable' ).on("change",'.datepicker',function() {
        $( this ).datepicker( "option", "dateFormat", "yy-mm-dd" );
      });
    });
    

    【讨论】:

    • 这与我的回答相同,只是您不需要听整个文档 - 这会大大降低您的脚本速度,尤其是对于大页面。您只需要委托最近的共同父母。
    • 我刚刚发现。我编辑了我的答案,并对你的答案投了赞成票。
    • 这不会在新的日期选择器元素上初始化日期选择器。
    • 它仍然不适合我,我应该如何在新的 datepickers 元素上初始化 datepicker?
    • @Annatar 你看我的回答了吗?
    【解决方案3】:

    您不需要事件委托;只需在开始时设置您的选项。然后,在您的函数中,在添加新元素时触发 datepicker 方法(使用所需的选项)。

    $(".datepicker").datepicker("option", "dateFormat", "yy-mm-dd");
    
    function addRow() {   
        var table = document.getElementById("TheTable");
        var row = table.insertRow(-1);
        var cell1 = row.insertCell(0);
        var cell2 = row.insertCell(1);
        cell1.innerHTML='Date';
        $('<input type="text" class="datepicker"/>')
            .datepicker("option", "dateFormat", "yy-mm-dd")
            .appendTo(cell2);
    }
    

    【讨论】:

    • 在将其设置为日期选择器之前,您将如何使用 datepicker 选项方法在输入上设置日期选择器选项?
    猜你喜欢
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 2012-10-21
    相关资源
    最近更新 更多