DOM mutation events replacement

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-26 17:32:24

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:

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).

Petr Janeček

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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!