简体   繁体   中英

Why does my jQuery delegated click fire multiple times?

I am copying an element and adding it to aa list of elements. First, I get some HTML using an ajax call:

var setButtonClick = function (url, btn) {
    $.ajax(url, $('form').serialize(), 'Html').then(function (data) {
        $(btn).parent().find(sel.addListItem).on('click', function () {
            addListItem(data, this, btn);              
        });

        addListItem(data, btn, btn);          
    });
}

addListItem looks like this:

var addListItem = function (data, context, btn) {
    
    var $template = $(data);
    // stuff not related removed for brevity
          
    $(btn).before($template);      
}

I then have a remove function using a delegate:

 $(sel.editableList).delegate(sel.removeListItem, 'click', function () {
     // fires once for every element with the sel.removeListItem selector
 }

I need the click event to fire once for the clicked element only. I can get a basic version of delegate working by inserting content like this:

$( "body" ).delegate( "p", "click", function() {
    $( this ).after( "<p>Another paragraph!</p>" );
});

Therefore, I'm thinking it may be because I'm inserting a copy of the element or is it the same element I'm adding over and over? I've also tried to use clone to create a new element before inserting like:

 var $template = $(data).clone();

Can anyone show me where I am going wrong with this please?

The problem is that every time your ajax is called you attach a click event handler to the elements. It gets called repeatedly, because you add it to the elements that already existed and had this handler attached.

The solution for your problem is to detach previously attached handlers with off() function.

var setButtonClick = function (url, btn) {
    $.ajax(url, $('form').serialize(), 'Html').then(function (data) {
        $(btn).parent().find(sel.addListItem)
            .off('click')
            .on('click', function () {
                addListItem(data, this, btn);              
            });

        addListItem(data, btn, btn);          
    });
}

#

In the future you may want to attach different click event handlers or may want to turn off specific handlers, for that you could use namespaces.

$(elem).on('event.namespace', function(){});
$(elem).off('event.namespace');

That way you could have multiple click event handlers on one element. This would be the code if you have more than one click event handlers

var setButtonClick = function (url, btn) {
    $.ajax(url, $('form').serialize(), 'Html').then(function (data) {
        $(btn).parent().find(sel.addListItem)
            .off('click.addItem')
            .on('click.addItem', function () {
                addListItem(data, this, btn);              
            });

        addListItem(data, btn, btn);          
    });
}

#

And here's the example.

 $('.btn').on('click.ns1', function(){ alert('Hey'); }); $('.btn').on('click.ns2', function(){ alert('How you doin?'); }); // Comment me out to see the difference $('.btn').off('click.ns2');
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button class="btn">Click me</button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM