218 votes

jQuery - Déclenchement d'un événement lorsqu'un élément est supprimé du DOM

J'essaie de comprendre comment exécuter un code js lorsqu'un élément est supprimé de la page :

jQuery('#some-element').remove(); // remove some element from the page
/* need to figure out how to independently detect the above happened */

Y a-t-il un événement adapté pour cela, quelque chose comme :

jQuery('#some-element').onremoval( function() {
    // do post-mortem stuff here
});

1 votes

Par curiosité, que voulez-vous faire avec l'élément qui a été retiré ?

8 votes

J'ai un élément qui s'attache indépendamment à la pièce que j'enlève, donc je veux détecter quand cette pièce est partie pour éliminer cet élément aussi. Je pourrais revoir la conception de l'ensemble, mais l'accomplissement de ce qui précède me fera gagner beaucoup de temps (et de code).

196voto

mtkopone Points 1607

Vous pouvez utiliser Événements spéciaux jQuery pour ça.

En toute simplicité,

Mise en place :

(function($){
  $.event.special.destroyed = {
    remove: function(o) {
      if (o.handler) {
        o.handler()
      }
    }
  }
})(jQuery)

Uso:

$('.thing').bind('destroyed', function() {
  // do stuff
})

Addendum pour répondre aux commentaires de Pierre et DesignerGuy :

Pour que le rappel ne soit pas déclenché lors de l'appel $('.thing').off('destroyed') changez la condition if en : if (o.handler && o.type !== 'destroyed') { ... }

15 votes

Très bonne solution. Ben Alman a rédigé un article sur les événements spéciaux pour plus d'informations : benalman.com/news/2010/03/jquery-special-events

11 votes

+1 avait réussi à passer complètement à côté de ces événements spéciaux jusqu'à maintenant, fichu utile ! Une chose à dire, ayant juste implémenté ce qui précède, il serait préférable de modifier les éléments suivants o.handler() a o.handler.apply(this,arguments) sinon l'événement et les objets de données ne sont pas transmis par l'écouteur d'événement.

1 votes

Je suis d'accord, c'est la meilleure solution à la question.

121voto

Philipp Munin Points 1552

Je viens de vérifier, c'est déjà intégré dans la version actuelle de JQuery :

jQuery - v1.9.1

jQuery UI - v1.10.2

$("#myDiv").on("remove", function () {
    alert("Element was removed");
})

Important : Il s'agit d'une fonctionnalité de Jquery UI script (pas JQuery), donc vous devez charger les deux scripts (jquery et jquery-ui) pour que cela fonctionne. Voici un exemple : http://jsfiddle.net/72RTz/

11 votes

Cela a été très utile. J'ai appris que cette fonctionnalité se trouve dans le composant "Widget" de jQuery UI si vous ne cherchez pas à télécharger toute la bibliothèque UI.

5 votes

Est-ce que cela est documenté quelque part ? J'ai parcouru la documentation du widget jQuery UI et je n'ai pas trouvé de mention à ce sujet. J'aimerais savoir si cette fonctionnalité est officiellement prise en charge et s'il existe des réserves quant à son utilisation...

0 votes

Celle-ci ne fonctionne pas - j'ai essayé avec jQuery 1.10.2, mais la réponse ci-dessous de @mtkopone fonctionne parfaitement, c'est pourquoi je voterais pour la mise à jour de la réponse à cette question

56voto

Adam Points 8165

Vous pouvez vous lier à l'événement DOMNodeRemoved (partie de DOM Level 3 WC3 spec).

Fonctionne dans IE9, les dernières versions de Firefox et Chrome.

Exemple :

$(document).bind("DOMNodeRemoved", function(e)
{
    alert("Removed: " + e.target.nodeName);
});

Vous pouvez également recevoir une notification lors de l'insertion d'éléments en liant les données à l'adresse suivante DOMNodeInserted

13 votes

Note : "L'ajout d'écouteurs de mutation DOM à un document dégrade profondément les performances des autres modifications DOM apportées à ce document (les rendant de 1,5 à 7 fois plus lentes !)" de : developer.mozilla.org/fr/DOM/Mutation_events

1 votes

J'adore ça, même si le nodeName est rarement utile pour moi. J'utilise simplement e.target.className o if ($(e.target).hasClass('my-class')) { ... .

0 votes

Cela ne fonctionne pas sur l'élément lui-même, mais seulement sur ses enfants.

38voto

David Points 36241

Il n'existe pas d'événement intégré pour la suppression des éléments, mais vous pouvez en créer un en simulant une extension de la méthode de suppression par défaut de jQuery. Notez que le callback doit être appelé avant la suppression effective de l'élément pour conserver la référence.

(function() {
    var ev = new $.Event('remove'),
        orig = $.fn.remove;
    $.fn.remove = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

$('#some-element').bind('remove', function() {
    console.log('removed!');
    // do pre-mortem stuff here
    // 'this' is still a reference to the element, before removing it
});

// some other js code here [...]

$('#some-element').remove();

Note : certains problèmes liés à cette réponse ont été soulignés par d'autres posteurs.

  1. Cela ne fonctionnera pas si le nœud est supprimé par l'intermédiaire de la fonction html() replace() ou d'autres méthodes jQuery
  2. Cet événement fait des bulles
  3. jQuery UI supprime également les surcharges.

La solution la plus élégante à ce problème semble être : https://stackoverflow.com/a/10172676/216941

2 votes

Merci pour cela ! Un petit ajout : parce que l'événement "remove-event" surgit, vous le recevrez également lorsqu'un enfant est retiré, donc il vaut mieux écrire le gestionnaire de cette façon : $('#some-element').bind('remove', function(ev) { if (ev.target === this) { console.log('removed!'); } });

3 votes

Cela n'a pas fonctionné tout de suite pour moi - j'ai dû renvoyer le résultat de orig.apply.

0 votes

Ce n'est pas une réponse exacte. Voir ma réponse

33voto

Hazy Joe Aardvark Points 1389

Accrochage .remove() n'est pas la meilleure façon de gérer cette situation, car il existe de nombreuses façons de supprimer des éléments de la page (par exemple, en utilisant la fonction .html() , .replace() etc).

Afin d'éviter divers risques de fuite de mémoire, en interne, jQuery essaiera d'appeler la fonction jQuery.cleanData() pour chaque élément retiré, quelle que soit la méthode utilisée pour le retirer.

Voir cette réponse pour plus de détails : fuites de mémoire en javascript

Donc, pour de meilleurs résultats, vous devriez accrocher le cleanData qui est exactement ce que le jquery.event.destroyed Le plugin le fait :

http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js

0 votes

Ce point de vue sur cleanData a été très utile pour moi ! Merci beaucoup, Joe :)

1 votes

Belle réponse, mais cela ne fonctionne que pour les méthodes jQuery. Si vous intégrez une autre plateforme qui peut vous couper l'herbe sous le pied, la réponse d'Adam est la plus logique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X