最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - appending element and removing it destroys all event handlers in jquery? - Stack Overflow

programmeradmin1浏览0评论

Ok I create element, assign click handler, and append it to body. Then i remove it and reappend it and click handler is no longer working???

Why would this happen.

var btn = $('<button>').text('hi').click(function(){console.log(3);});
var div = $('<div>');
div.append(btn);
$('body').append(div);
//click it now, it works..
div.html('');
div.append(btn);
// now button doesn't work..

So why is this happening and what can i do to fix it.

Ok I create element, assign click handler, and append it to body. Then i remove it and reappend it and click handler is no longer working???

Why would this happen.

var btn = $('<button>').text('hi').click(function(){console.log(3);});
var div = $('<div>');
div.append(btn);
$('body').append(div);
//click it now, it works..
div.html('');
div.append(btn);
// now button doesn't work..

So why is this happening and what can i do to fix it.

Share Improve this question asked Apr 5, 2015 at 20:38 Muhammad UmerMuhammad Umer 18.1k24 gold badges109 silver badges174 bronze badges 2
  • don't know exactly, but could it be its because you do not close the div tag . and i have never seen a jQuery selector with <> like you have – Timotheus0106 Commented Apr 5, 2015 at 20:48
  • 2 @TimotheusTriebl <*> is not a selector, it's used by jQuery for a creating corresponding DOM elements. – Ram Commented Apr 5, 2015 at 20:51
Add a comment  | 

4 Answers 4

Reset to default 10

Since .html('') is essentially the same as .empty(), the following applies (from the jQuery docs):

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.

If you want to remove elements without destroying their data or event handlers (so they can be re-added later), use .detach() instead.

One option would be to use event delegation. In doing so, the event isn't bound directly to the button element, it is bound to a constant parent element that isn't removed.

Example Here

$(document).on('click', 'button', function () {
    // ..
});

As mentioned above, another option would be to use the .detach() method in order to remove the element from the DOM, without removing attached event listeners.

The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.

Example Here

div.find('button').detach();
div.append(btn);

put this after the second div.append(btn); - > btn = $('button').text('hi').click(function(){console.log(3);});

This is very interesting situation. What happens when you clear div with html('') method. Take a look at source code and you will see that internally jQuery calls jQuery.cleanData(getAll(elem, false));. This method is responsible for removing all the related data for all child elements that have already been removed. This is important in order to avoid memory leaks.

Clearing data also removes events bound with on (and similar) methods, because those event handlers are also stored in internal cache object.

So as the result, even though you removed content of the div, the btn object is still in memory, but the event bound to it previously is gone.

This was the explanation of the problem. The solution is to use dedicated method called detach. It will remove button from the DOM but will keep event data in case element will later be appended again.

// remove element but keep its data
btn.detach();

// append back
div.append(btn);

In situations like this you should not use html('').

It happens because you're calling html() on the DIV that contains the button.

When you call html() with an empty string, it calls empty() internally.
Calling empty() on an element iterates over all the elements inside that element removing all data and events securely.

It does this by calling jQuery.cleanData on the button, which again explicitly calls jQuery.removeEvent, removing all events on the button.

The button is still stored in the variable btn, so it can be appended again, but it has lost all data and any events attached to it because the parent element had html("") called on it.

The solution is to use detach() to remove the element with all the data and events intact, so it can be appended again, or you can attach the event to a parent element that isn't removed, or you could just hide the element, generally there's no reason to remove the element just to reappend it, it's better to hide it.

FIDDLE

发布评论

评论列表(0)

  1. 暂无评论