问题
I am trying to make a function go off when a particular div is created. In the simplest of terms, I have something like this:
<a href=\"\" id=\"foo\">Click me!</a>
<script>
$(\"#foo\").live(\"click\",function(e) {
e.preventDefault();
$(this).append($(\"<div />\").html(\"new div\").attr(\"id\",\"bar\"));
});
</script>
Before, I had mutation events listen for the creation of div#bar - something like this:
$(\"#bar\").live(\"DOMNodeInserted\", function(event) {
console.log(\"a new div has been appended to the page\");
});
Is there an equivalent using Mutation Observers? I tried attrchange.js featured on Can you have a javascript hook trigger after a DOM element's style object changes? but that plugin only detects when an element has been modified, not when it\'s created.
回答1:
This is code that listens for mutations on the childlist of #foo
and checks to see if a child with the id of bar
is added.
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
$("#foo").live("click",function(e) {
e.preventDefault();
$(this).append($("<div />").html("new div").attr("id","bar"));
});
// define a new observer
var obs = new MutationObserver(function(mutations, observer) {
// look through all mutations that just occured
for(var i=0; i<mutations.length; ++i) {
// look through all added nodes of this mutation
for(var j=0; j<mutations[i].addedNodes.length; ++j) {
// was a child added with ID of 'bar'?
if(mutations[i].addedNodes[j].id == "bar") {
console.log("bar was added!");
}
}
}
});
// have the observer observe foo for changes in children
obs.observe($("#foo").get(0), {
childList: true
});
However, this only observes #foo
. If you want to look for the addition of #bar
as a new child of other nodes, you need to observe those potential parents with additional calls to obs.observe()
. To observe a node with the id of baz
, you might do:
obs.observe($('#baz').get(0), {
childList: true,
subtree: true
});
The addition of the subtree
option means that the observer will look for the addition of #bar
as either a child or a deeper descendant (e.g. grandchild).
回答2:
When using jQuery, the usage of MutationObservers can be simplified as shown below.
$("#btnAddDirectly").click(function () {
$("#canvas").append($('<span class="stuff">new child direct</span>'));
});
$("#btnAddAsChildOfATree").click(function () {
$("#canvas").append($('<div><div><span class="stuff">new child tree</span></div></div>'));
});
var obs = new MutationObserver(function(mutations, observer) {
// using jQuery to optimize code
$.each(mutations, function (i, mutation) {
var addedNodes = $(mutation.addedNodes);
var selector = "span.stuff"
var filteredEls = addedNodes.find(selector).addBack(selector); // finds either added alone or as tree
filteredEls.each(function () { // can use jQuery select to filter addedNodes
alert('Insertion detected: ' + $(this).text());
});
});
});
var canvasElement = $("#canvas")[0];
obs.observe(canvasElement, {childList: true, subtree: true});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="canvas">
Canvas
</div>
<button id="btnAddDirectly">Add span directly to canvas</button>
<button id="btnAddAsChildOfATree">Add span as child of a tree</button>
It is always important to notice, the second argument to .observe()
, MutationObserverInit
, is important:
In the options, use childList: true
if the span
will only be added as a direct child. subTree: true
if it can be at any level down below #canvas
.
From the docs:
childList
: Set totrue
if additions and removals of the target node's child elements (including text nodes) are to be observed.subtree
: Set totrue
if mutations to target and target's descendants are to be observed.
来源:https://stackoverflow.com/questions/13277212/mutation-observer-for-creating-new-elements