【问题标题】:Event binding with Static Ancestors leads to every click event being triggered与静态祖先的事件绑定导致触发每个点击事件
【发布时间】:2019-06-15 00:50:20
【问题描述】:

我创建了一个应该允许用户创建的小型测试应用程序:

  • 创建列表元素
  • 移除列表元素
  • 创建列表
  • 删除列表

我了解到动态添加的元素不会获得绑定到它们的事件(基于此:Event binding on dynamically created elements?),因此我尝试将事件附加到单个静态祖先上。不幸的是,这会导致每一个点击事件都在按下一个按钮时被触发。

<head>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    <title>Test Page</title>
</head>
<body>
    <div id="container">
        <div class="listContainer">
            <ol>
                <li>First list <button class="btnDeleteListItem">Delete</button></li>
                <li>First list <button class="btnDeleteListItem">Delete</button></li>
                <li>First list <button class="btnDeleteListItem">Delete</button></li>
            </ol>
            <button class="btnAddListElement">+Add List Item</button>
            <button class="btnDeleteList">Delete List</button>
        </div>
        <button class="btnAddList">+Add List</button>
    </div>
</body>
<script>
var btnDeleteListItem = $(".btnDeleteListItem");
var btnAddListElement = $(".btnAddListElement");
var btnDeleteList = $(".btnDeleteList");
var btnAddList = $(".btnAddList");
var container = $("#container");

container.on("click",btnDeleteListItem, function (e) {
    $(this).parent().remove();
    console.log("list item deleted");
});

container.on("click",btnAddListElement, function (e) {
    var html = '<li> Just added <button class="btnDeleteListItem">Delete</button></li>';
    $("ol").append(html);
    console.log("list item added");
});

container.on("click",btnDeleteList, function (e) {
    $(this).parent().remove();
    console.log("list deleted");
});

btnAddList.on("click", function(e){
    var html = '<div class="listContainer"><ol><li>Other list <button class="btnDeleteListItem">Delete</button></li><li>Other list <button class="btnDeleteListItem">Delete</button></li><li>Other list <button class="btnDeleteListItem">Delete</button></li></ol><button class="btnAddListElement">+Add List Item</button><button class="btnDeleteList">Delete List</button></div>';
    $(html).insertBefore($(this));
    console.log("list added");
});
</script>

</html>`

有没有办法隔离点击事件?

【问题讨论】:

    标签: javascript jquery uielement


    【解决方案1】:

    问题在于,尽管您使用的是委托事件处理程序,但您只是在加载 DOM 时选择元素。要解决此问题,请将选择器参数作为字符串传递给 on()。这样,选择器将与 click 事件通过 #container 进行匹配,而不仅仅是特定元素实例。

    还请注意,您需要在与单击的.btnAddListElement 按钮相关的ol 上仅调用append(),否则您最终会添加一个新的@987654327 @ 到每个列表。为此,请将$('ol') 更改为$(this).prev('ol')。

    var $container = $("#container");
    
    $container.on("click", ".btnDeleteListItem", function(e) {
      $(this).parent().remove();
      console.log("list item deleted");
    });
    
    $container.on("click", '.btnAddListElement', function(e) {
      var html = '<li> Just added <button class="btnDeleteListItem">Delete</button></li>';
      $(this).prev("ol").append(html);
      console.log("list item added");
    });
    
    $container.on("click", '.btnDeleteList', function(e) {
      $(this).parent().remove();
      console.log("list deleted");
    });
    
    $container.on('click', '.btnAddList', function(e) {
      var html = '<div class="listContainer"><ol><li>Other list <button class="btnDeleteListItem">Delete</button></li><li>Other list <button class="btnDeleteListItem">Delete</button></li><li>Other list <button class="btnDeleteListItem">Delete</button></li></ol><button class="btnAddListElement">+Add List Item</button><button class="btnDeleteList">Delete List</button></div>';
      $(html).insertBefore($(this));
      console.log("list added");
    });
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    
    <div id="container">
      <div class="listContainer">
        <ol>
          <li>First list <button class="btnDeleteListItem">Delete</button></li>
          <li>First list <button class="btnDeleteListItem">Delete</button></li>
          <li>First list <button class="btnDeleteListItem">Delete</button></li>
        </ol>
        <button class="btnAddListElement">+Add List Item</button>
        <button class="btnDeleteList">Delete List</button>
      </div>
      <button class="btnAddList">+Add List</button>
    </div>

    【讨论】:

    • 非常感谢,我以为我通过不使用基于字符串的选择器参数来使我的代码更简洁。另外,感谢您指出 $(this).prev('ol') 我要花一辈子才能找到那个。
    • 很高兴为您提供帮助。作为参考,在大多数情况下缓存选择器是一件好事,但在处理委托事件时则不然。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2021-04-11
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 2019-12-14
    • 2013-07-31
    • 1970-01-01
    相关资源
    最近更新 更多