Mutation Observer для создания новых элементов
Я пытаюсь отключить функцию при создании определенного div. Проще говоря, у меня есть что-то вроде этого:
<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>
Раньше я слушал события мутации для создания div # bar - что-то вроде этого:
$("#bar").live("DOMNodeInserted", function(event) {
console.log("a new div has been appended to the page");
});
Есть ли аналог, использующий Mutation Observers? Я попытался использовать attrchange.js, который был включен. У вас может быть триггер javascript-хука после изменения стиля объекта DOM-элемента? но этот плагин обнаруживает только когда элемент был изменен, а не когда он создан.
3 ответа
Это код, который прослушивает мутации в дочернем списке #foo
и проверяет, есть ли ребенок с идентификатором bar
добавлен.
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
});
Тем не менее, это только наблюдает #foo
, Если вы хотите посмотреть на добавление #bar
как новый ребенок других узлов, вам нужно наблюдать за этими потенциальными родителями с дополнительными вызовами obs.observe()
, Наблюдать узел с идентификатором baz
вы могли бы сделать:
obs.observe($('#baz').get(0), {
childList: true,
subtree: true
});
Дополнение subtree
опция означает, что наблюдатель будет искать дополнение #bar
как ребенок или более глубокий потомок (например, внук).
При использовании jQuery использование MutationObserver может быть упрощено, как показано ниже.
$("#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>
Всегда важно заметить, второй аргумент .observe()
, MutationObserverInit
, это важно:
В настройках используйте childList: true
если span
будет добавлен только как прямой ребенок. subTree: true
если это может быть на любом уровне ниже #canvas
,
Из документов:
childList
: Установлен вtrue
если должны наблюдаться добавления и удаления дочерних элементов целевого узла (включая текстовые узлы).subtree
: Установлен вtrue
если мутации в цель и потомки цели должны наблюдаться.
Наблюдатель за мутациями
// Select the node that will be observed for mutations
const targetNode = document.getElementById('some-id');
// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: true, subtree: true };
// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
// Use traditional 'for loops' for IE 11
for(const mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
}
else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
// Later, you can stop observing
observer.disconnect();
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver