2010-12-30 15 views
57

¿hay alguna forma de desencadenar evento (puede ser personalizado) en el cambio de atributo?evento de disparo en el atributo DOM cambio

Digamos, cuando se cambia IMG src o innerHtml de DIV?

+0

Un complemento de consulta haría eso. https://stackoverflow.com/questions/16781778/detecting-attribute-change-of-value-of-an-attribute-i-made/29978836#29978836 – Kavi

Respuesta

47

Nota: A partir de 2012, los eventos de mutación se han eliminado del estándar y ahora están en desuso. Consulte otras respuestas o documentación sobre cómo usar su reemplazo, MutationObserver.

Usted está haciendo referencia a DOM Mutation Events. El soporte del navegador es pobre (pero mejora) para estos eventos. Mutation Events plugin for jQuery puede llevarte un poco del camino.

+6

Eventos de mutación DOM en realidad son razonablemente compatibles con los navegadores. Es solo que IE no los admite en absoluto (aunque IE 9 lo hará). –

+4

@TimDown si se trata de IE, no es algo extraño. –

+11

Estos ahora están en desuso en favor de ' MutationObserver', https: //developer.mozilla.org/es-ES/docs/Web/API/MutationObserver – DanielB

3

No hay un evento de dom nativo en el que se pueda conectar.

Buen artículo here que intenta proporcionar una solución en forma de un plugin jquery.

Código del artículo

$.fn.watch = function(props, callback, timeout){ 
    if(!timeout) 
     timeout = 10; 
    return this.each(function(){ 
     var el  = $(this), 
      func = function(){ __check.call(this, el) }, 
      data = { props: props.split(","), 
         func: callback, 
         vals: [] }; 
     $.each(data.props, function(i) { 
       data.vals[i] = el.css(data.props[i]); 
     }); 
     el.data(data); 
     if (typeof (this.onpropertychange) == "object"){ 
      el.bind("propertychange", callback); 
     } else if ($.browser.mozilla){ 
      el.bind("DOMAttrModified", callback); 
     } else { 
      setInterval(func, timeout); 
     } 
    }); 
    function __check(el) { 
     var data = el.data(), 
      changed = false, 
      temp = ""; 
     for(var i=0;i < data.props.length; i++) { 
      temp = el.css(data.props[i]); 
      if(data.vals[i] != temp){ 
       data.vals[i] = temp; 
       changed = true; 
       break; 
      } 
     } 
     if(changed && data.func) { 
      data.func.call(el, data); 
     } 
    } } 
+0

¿qué ocurre con el rendimiento de intervalo de 10ms con mayor uso? – pie6k

+0

Existen implicaciones de rendimiento bastante grandes con este enfoque. –

+0

"Artículo bueno" enlace roto :( – Richardissimo

6

Si sólo necesita algo específico, entonces un simple setInterval() trabajará, comprobando el atributo de destino (s) cada pocos milisegundos:

var imgSrc = null; 
setInterval(function() { 
    var newImgSrc = $("#myImg").attr("src"); 
    if (newImgSrc !== imgSrc) { 
     imgSrc = newImgSrc; 
     $("#myImg").trigger("srcChange"); 
    } 
}, 50); 

A continuación, se unen a la costumbre "srcChange" evento:

$("#myImg").bind("srcChange", function() {....}); 
+22

el uso de intervalos para esto es realmente pobre en mi opinión (sí es 'una' forma). – EricG

+1

El uso de intervalos es apropiado en cantidades limitadas, especialmente donde el rendimiento no se convertirá en un problema. No he realizado ninguna prueba de banco, pero sé por experiencia que puedo manipular todo tipo de propiedades en el DOM en un intervalo rápido sin notar la degradación del rendimiento. – Xaxis

32

Cómo configurar un MutationObserver, principalmente copiado de MDN pero he agregado mis propios comentarios para mayor claridad.

window.MutationObserver = window.MutationObserver 
    || window.WebKitMutationObserver 
    || window.MozMutationObserver; 
// Find the element that you want to "watch" 
var target = document.querySelector('img'), 
// create an observer instance 
observer = new MutationObserver(function(mutation) { 
    /** this is the callback where you 
     do what you need to do. 
     The argument is an array of MutationRecords where the affected attribute is 
     named "attributeName". There is a few other properties in a record 
     but I'll let you work it out yourself. 
     **/ 
}), 
// configuration of the observer: 
config = { 
    attributes: true // this is to watch for attribute changes. 
}; 
// pass in the element you wanna watch as well as the options 
observer.observe(target, config); 
// later, you can stop observing 
// observer.disconnect(); 

Espero que esto ayude.

+0

Funciona como un encanto en Chrome. ¡Realmente util! –

0

Además de Mats' answer inspirado por MDN's MutationObserver Example usage:

Si sus opciones contienen <property>: true y planea cambiar esta propiedad de objetivo dentro de la función de devolución de llamada MutationObserver 's, utilice el siguiente para evitar que las llamadas recursivas - hasta tiempo de espera de secuencia de comandos, desbordamiento de pila o similar:

... 
// Used to prevent recursive calls of observer's callback function 
// From https://stackoverflow.com/questions/4561845/firing-event-on-dom-attribute-change 
let insideInitialObserverCallback = false 

let callback = function(mutationsList) { 
    insideInitialObserverCallback = ! insideInitialObserverCallback 
    if (insideInitialObserverCallback) { 

     // ... change target's given property ...  

    } 
}) 

let observer = new MutationObserver(callback); 
... 
Cuestiones relacionadas