开发者

DOM mutation events replacement

开发者 https://www.devze.com 2023-02-19 23:51 出处:网络
Since DOM mutation 开发者_StackOverflowis marked as deprecated by the w3c (see http://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents), is there an (fast) alternative way to detect attribute m

Since DOM mutation 开发者_StackOverflowis marked as deprecated by the w3c (see http://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents), is there an (fast) alternative way to detect attribute modification in the DOM ?


The reason that mutation events was deprecated was because of huge performance issues.

The replacement is Mutation Observers, look at http://updates.html5rocks.com/2012/02/Detect-DOM-changes-with-Mutation-Observers and https://developer.mozilla.org/en/DOM/DOM_Mutation_Observers

Information about mutations is delivered to observers as an ordered sequence of MutationRecords, representing an observed sequence of changes that have occurred

Sample usage:

    var observer = new MutationObserver(function(mutationRecords) {
    // Handle mutations
     });

    observer.observe(myNode,
     {  // options:
     subtree: true,  // observe the subtree rooted at myNode
     childList: true,  // include information childNode insertion/removals
     attribute: true  // include information about changes to attributes within the subtree
    });

This is supported in Chrome 18 and Firefox and Webkit nightly builds. Firefox 14 will also be supporting this feature.


A great replacement for the deprecated DOM* events is animationStart in conjunction with CSS Animations. David Walsh writes about the method.

First, set up the keyframes and apply it to the elements you'd like to listen for (don't forget the vendor prefixes!):

@keyframes nodeInserted {  
  from { clip: rect(1px, auto, auto, auto); }
  to { clip: rect(0px, auto, auto, auto); }  
}

#parentElement > li {
  animation-duration: 0.001s;
  animation-name: nodeInserted;
}

Next, add the listener:

var insertListener = function(event){
  if (event.animationName == "nodeInserted") {
    // This is the debug for knowing our listener worked!
    // event.target is the new node!
    console.warn("Another node has been inserted! ", event, event.target);
  }
}
document.addEventListener("animationstart", insertListener, false); // standard + firefox
document.addEventListener("MSAnimationStart", insertListener, false); // IE
document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari

Ta-da! Here is David's demo. It works great for me on a Chrome extension that adds Facebook pictures to Google Voice (see content.css and injected.js).


A year later, there are the new and shiny Mutation Observers from DOM Level 4 (follow the links there, they explain a lot!). Where a Mutation Event fired a thousand times, MutationObserver fires only once with all the modifications contained and accessible.

Works for (as of 2017/03):

  • Firefox 14+
  • IE 11
  • Edge
  • Opera 15+
  • Chrome 26+ (18 till 25 prefixed, window.WebKitMutationObserver)
  • Safari 6.0 (prefixed, window.WebKitMutationObserver)


As far as I know there is no alternative (yet) so you are stuck with DOMAttrModified which is only supported in Firefox and Opera. In IE you have the onpropertychanged event but there is no way to get similar functionality in Chrome/Safari. There are a number of things you could do depending on what you are trying to accomplish and the browsers you are targetting:

  • define getters and setters to the attributes you want to monitor
  • override methods like document.createAttribute, attributes.setNamedItem, ...

I've been working on a cross-browser solution myself but without much success. You should stay away from mutation events all together since they are not cross-browser and very slow. There are good reasons why they are deprecated. If you want to learn more read this:

  • http://www.w3.org/2008/webapps/wiki/MutationReplacement
  • http://www.quirksmode.org/dom/events/ > W3C events
  • http://robertnyman.com/javascript/javascript-getters-setters.html
0

精彩评论

暂无评论...
验证码 换一张
取 消