Jquery ajax 调用后事件绑定两次

Jquery Event bound twice after ajax call

我想在通过 ajax 调用动态创建的元素上绑定一个事件。 一些元素已经存在,并且在页面加载时将事件与它们绑定。但是当在 ajax 调用之后创建新元素时,新元素将失去它们的绑定。

我搜索了一下,找到了一个很好的解决方案。 Jquery Event won't fire after ajax call

在这个问题中 "Jason Fingar" 提出了两个解决方案来解决这个问题

这是他提出的第一个解决方案

"1) Encapsulate your "binding" code and call it both on page load and immediately after the element in question gets added back to the page. For example:"

$(document).ready(function(){
// bind event handlers when the page loads.
bindButtonClick();
});

function bindButtonClick(){
$('.myClickableElement').click(function(){
    ... event handler code ...
});
}

function updateContent(){
$.ajax({
    url : '/ajax-endpoint.php',
    data : {'onMyWay' : 'toServer'},
    dataType : 'html',
    type : 'post',
    success : function(responseHtml){
        // .myClickableElement is replaced with new (unbound) html 
     element(s)
        $('#container').html(responseHtml);

        // re-bind event handlers to '.myClickableElement'
        bindButtonClick();  
    }
});
}

我遇到了什么问题? 该事件与新元素成功绑定,但对于旧元素或页面加载时加载的元素,该事件被绑定两次。 这有什么问题?

jQuery 在为同一事件绑定侦听器之前不会检查事件侦听器是否已绑定到元素。在您的代码中,.myClickableElement 选择所有此类元素,并且对于现有元素,将添加重复的侦听器。

首先取消绑定事件侦听器

解决此问题的一种方法是先删除侦听器,然后重新绑定它。这样对于每个目标元素都会存在一次。

function bindButtonClick(){
  $('.myClickableElement').off('click').on('click', function(){
    ... event handler code ...
  });
}

通过在父元素上使用事件委托

另一种(但有效的)方法是对子元素使用事件委托。我不太了解你的 HTML,但你可以在父元素上执行此操作(.parent 这里是所有 .myClickableElement 元素的父元素):

$('.parent').on('click', '.myClickableElement', function() {
  ... event handler code ...
});

这也将为那些元素启用事件绑定,当此代码执行时,这些元素不存在于 DOM 中。所以这将是您问题的通用解决方案,并且在 AJAX 完成时您不需要绑定侦听器。

您可以使用 document.on 或父容器委托 cilck 事件,这将适用于现有元素和动态创建的元素,无需从内部 ajax 调用

$(document).ready(function(){
   // If you know that elements for which click handler required can be anywhere in the document
   /*$(document).on('click', '.myClickableElement', function(){
    ... event handler code ...
   });*/

   //If you are sure that elements to which click event handler required is belongs to container elements
   $('#container').on('click', '.myClickableElement', function(){
    ... event handler code ...
   });
});

function updateContent(){
$.ajax({
    url : '/ajax-endpoint.php',
    data : {'onMyWay' : 'toServer'},
    dataType : 'html',
    type : 'post',
    success : function(responseHtml){
        // .myClickableElement is replaced with new (unbound) html 
     element(s)
        $('#container').html(responseHtml);

        // re-bind event handlers to '.myClickableElement'
        //bindButtonClick();   -- not required to bind again
    }
});
}

您必须使用取消绑定方法取消绑定为您的元素委托的事件,然后重新绑定它。

$('.myClickableElement').unbind('click').bind('click', function(){
    // action goes here
});

如果您的 .myClickableElement 已经有一个附加事件,您可以通过解除绑定将其删除。

为了获得更好的方法,请检查此 documentation