J'utilise .on()
pour lier les événements de divs créés après le chargement de la page. Cela fonctionne bien pour cliquer, mouseenter ... mais j'ai besoin de savoir quand un nouveau div de la classe MyClass a été ajouté. Je recherche ceci:
$('#MyContainer').on({
wascreated: function () { DoSomething($(this)); }
}, '.MyClass');
Comment puis-je faire cela? J'ai réussi à écrire toute mon application sans plugin et je souhaite que cela reste ainsi.
Merci.
Réponses:
Auparavant, on pouvait se connecter à la
domManip
méthode de jQuery pour attraper toutes les manipulations de jQuery dom et voir quels éléments étaient insérés, etc. J'ai fait en sorte que l'internedomManip
méthode ne soit plus disponible en dehors du code jQuery principal.Les événements de mutation sont également obsolètes, car auparavant on pouvait faire quelque chose comme
$(document).on('DOMNodeInserted', function(e) { if ( $(e.target).hasClass('MyClass') ) { //element with .MyClass was inserted. } });
cela devrait être évité, et aujourd'hui les observateurs de mutation devraient être utilisés à la place, qui fonctionneraient comme ceci
var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation) if (mutation.addedNodes && mutation.addedNodes.length > 0) { // element added to DOM var hasClass = [].some.call(mutation.addedNodes, function(el) { return el.classList.contains('MyClass') }); if (hasClass) { // element has class `MyClass` console.log('element ".MyClass" added'); } } }); }); var config = { attributes: true, childList: true, characterData: true }; observer.observe(document.body, config);
la source
Voici mon plugin qui fait exactement cela - jquery.initialize
L'utilisation est la même que celle que vous utiliseriez pour la
.each
fonction, mais avec la.initialize
fonction sur l'élément, la différence.each
est qu'elle initialisera également les éléments ajoutés à l'avenir sans aucun code supplémentaire - peu importe si vous l'ajoutez avec AJAX ou autre chose.Initialize a exactement la même syntaxe qu'avec la fonction .each
$(".some-element").initialize( function(){ $(this).css("color", "blue"); });
Mais maintenant, si un nouvel élément correspondant au sélecteur d'élément .some apparaîtra sur la page, il sera instantanément initialisé. La façon dont un nouvel élément est ajouté n'est pas importante, vous n'avez pas besoin de vous soucier des rappels, etc.
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
Le plugin est basé sur
MutationObserver
la source
.initialize
fonctioncallback
uniquement pour les éléments ajoutés dynamiquement (par exemple via Ajax), et d'ignorer le rappel pour les éléments déjà présents lors du chargement initial de la page? J'essaye d'ajouter un paramètre àoptions
afin d'accomplir ceci, mais jusqu'à présent, je n'ai pas réussi à le faire.$('.myClass').addClass('ignore-initialize'); $.initialize('.myClass:not(.ignore-initialize)', callback);
Après avoir examiné ceci et plusieurs autres articles, j'ai essayé de distiller ce que je pensais être le meilleur de chacun en quelque chose de simple qui me permettait de détecter lorsqu'une classe d'éléments est insérée, puis d' agir sur ces éléments .
function onElementInserted(containerSelector, elementSelector, callback) { var onMutationsObserved = function(mutations) { mutations.forEach(function(mutation) { if (mutation.addedNodes.length) { var elements = $(mutation.addedNodes).find(elementSelector); for (var i = 0, len = elements.length; i < len; i++) { callback(elements[i]); } } }); }; var target = $(containerSelector)[0]; var config = { childList: true, subtree: true }; var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; var observer = new MutationObserver(onMutationsObserved); observer.observe(target, config); } onElementInserted('body', '.myTargetElement', function(element) { console.log(element); });
Ce qui est important pour moi, cela permet a) à l'élément cible d'exister à n'importe quelle profondeur dans "addedNodes" et b) la possibilité de traiter l'élément uniquement lors de son insertion initiale (pas besoin de rechercher l'ensemble du paramètre du document ou d'ignorer "déjà traité" drapeaux).
la source
if(mutation.addedNodes.length)
parce queaddedNodes
et lesremovedNodes
tableaux sont toujoursmutation
de typechildList
(vérifié dans IE11, Chrome53, FF49). Toujours +1, car la vôtre est la seule réponse où elleaddedNodes
est prise en compte (ellecallback
n'est appelée que lorsqu'un nœud est ajouté); non seulement sur ce fil, mais sur de nombreux autres fils. Tout le monde appelle simplement lecallback
pour toutes les mutations, même si le nœud est en cours de suppression.3 ans d'expérience plus tard, c'est ainsi que j'écoute "élément d'une certaine classe ajoutée au DOM" : vous ajoutez simplement un hook dans la
html()
fonction jQuery , comme ceci:function Start() { var OldHtml = window.jQuery.fn.html; window.jQuery.fn.html = function () { var EnhancedHtml = OldHtml.apply(this, arguments); if (arguments.length && EnhancedHtml.find('.MyClass').length) { var TheElementAdded = EnhancedHtml.find('.MyClass'); //there it is } return EnhancedHtml; } } $(Start);
Cela fonctionne si vous utilisez jQuery, ce que je fais. Et cela ne dépend pas de l'événement spécifique au navigateur
DOMNodeInserted
, qui n'est pas compatible avec plusieurs navigateurs. J'ai également ajouté la même implémentation pour.prepend()
Dans l'ensemble, cela fonctionne comme un charme pour moi et, espérons-le, pour vous aussi.
la source
html
pour modifier le DOM, pas seulement "en utilisant jQuery" en général. Les éléments ajoutés à l'aide, par exemple,jQuery.append
ne déclenchent pas cet événement.insertionQ('#intercom-container').every(function(/element){ element.style.display = 'none'; });
vous pourriez utiliser des événements de mutation
http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents
ÉDITER
depuis MDN: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events
Obsolète Cette fonctionnalité a été supprimée du Web. Bien que certains navigateurs puissent toujours le prendre en charge, il est en cours de suppression. Ne l'utilisez pas dans des projets anciens ou nouveaux. Les pages ou applications Web qui l'utilisent peuvent être interrompues à tout moment.
Les observateurs de mutation sont le remplacement proposé pour les événements de mutation dans DOM4. Ils doivent être inclus dans Firefox 14 et Chrome 18.
https://developer.mozilla.org/en/docs/Web/API/MutationObserver
MutationObserver
fournit aux développeurs un moyen de réagir aux changements dans un DOM. Il est conçu pour remplacer les événements de mutation définis dans la spécification des événements DOM3.Exemple d'utilisation
L'exemple suivant est tiré de http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/ .
// select the target node var target = document.querySelector('#some-id'); // create an observer instance var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); // configuration of the observer: var config = { attributes: true, childList: true, characterData: true }; // pass in the target node, as well as the observer options observer.observe(target, config); // later, you can stop observing observer.disconnect();
la source
Deux ajouts à la réponse d'Adeneo:
(1) nous pouvons changer la ligne
return el.classList.contains('MyClass');
À
if( el.classList ) { return el.classList.contains('MyClass'); } else { return false; }
Nous ne verrons donc pas l'
"Uncaught TypeError: Cannot read property 'contains' of undefined"
erreur.(2) Ajouter
subtree: true
àconfig
trouver des noeuds ajoutés récursive dans tous les éléments ajoutés.la source