일부 div 또는 입력이 HTML에 추가되면 함수를 실행하고 싶습니다. 이게 가능해?
예를 들어, 텍스트 입력이 추가되면 함수를 호출해야합니다.
답변
2015 업데이트, MutationObserver
최신 브라우저 에서 새로운 기능 지원 :
Chrome 18 세 이상, Firefox 14 이상, IE 11 이상, Safari 6 이상
이전 버전을 지원해야하는 경우 아래 5 년 전 답변 에서 언급 한 것과 같은 다른 방법으로 넘어 가려고 할 수 있습니다. 용이 있습니다. 즐겨 🙂
다른 사람이 문서를 변경하고 있습니까? 변경 사항을 완전히 제어 할 수 있으면 domChanged
함수 또는 사용자 지정 이벤트 를 사용하여 고유 한 API 를 만들고 수정하는 모든 곳에서 트리거 / 호출하면됩니다.
DOM 레벨 2는이 돌연변이 이벤트 유형을 하지만, IE의 이전 버전을 지원하지 않습니다. 돌연변이 이벤트 참고 DOM3 이벤트 사양에서 더 이상 사용되지 하고있는 성능 저하 .
onpropertychange
IE에서 돌연변이 이벤트를 에뮬레이션하려고 시도 할 수 있습니다 (그리고 그중 하나가 없다면 무차별 접근 방식으로 넘어갑니다).
A에 대한 전체 domChange 간격은 오버 죽일 수 있습니다. 전체 문서의 현재 상태를 저장하고 모든 요소의 모든 속성이 동일한 지 검사해야한다고 상상해보십시오.
요소와 순서에만 관심이 있다면 (질문에서 언급 한 것처럼) 효과가있을 getElementsByTagName("*")
수 있습니다. 요소를 추가하거나, 요소를 제거하거나, 요소를 바꾸거나 문서의 구조를 변경하면 자동으로 실행됩니다.
나는 개념 증명을 썼습니다 :
(function (window) {
var last = +new Date();
var delay = 100; // default delay
// Manage event queue
var stack = [];
function callback() {
var now = +new Date();
if (now - last > delay) {
for (var i = 0; i < stack.length; i++) {
stack[i]();
}
last = now;
}
}
// Public interface
var onDomChange = function (fn, newdelay) {
if (newdelay) delay = newdelay;
stack.push(fn);
};
// Naive approach for compatibility
function naive() {
var last = document.getElementsByTagName('*');
var lastlen = last.length;
var timer = setTimeout(function check() {
// get current state of the document
var current = document.getElementsByTagName('*');
var len = current.length;
// if the length is different
// it's fairly obvious
if (len != lastlen) {
// just make sure the loop finishes early
last = [];
}
// go check every element in order
for (var i = 0; i < len; i++) {
if (current[i] !== last[i]) {
callback();
last = current;
lastlen = len;
break;
}
}
// over, and over, and over again
setTimeout(check, delay);
}, delay);
}
//
// Check for mutation events support
//
var support = {};
var el = document.documentElement;
var remain = 3;
// callback for the tests
function decide() {
if (support.DOMNodeInserted) {
window.addEventListener("DOMContentLoaded", function () {
if (support.DOMSubtreeModified) { // for FF 3+, Chrome
el.addEventListener('DOMSubtreeModified', callback, false);
} else { // for FF 2, Safari, Opera 9.6+
el.addEventListener('DOMNodeInserted', callback, false);
el.addEventListener('DOMNodeRemoved', callback, false);
}
}, false);
} else if (document.onpropertychange) { // for IE 5.5+
document.onpropertychange = callback;
} else { // fallback
naive();
}
}
// checks a particular event
function test(event) {
el.addEventListener(event, function fn() {
support[event] = true;
el.removeEventListener(event, fn, false);
if (--remain === 0) decide();
}, false);
}
// attach test events
if (window.addEventListener) {
test('DOMSubtreeModified');
test('DOMNodeInserted');
test('DOMNodeRemoved');
} else {
decide();
}
// do the dummy test
var dummy = document.createElement("div");
el.appendChild(dummy);
el.removeChild(dummy);
// expose
window.onDomChange = onDomChange;
})(window);
용법:
onDomChange(function(){
alert("The Times They Are a-Changin'");
});
이것은 IE 5.5 이상, FF 2 이상, Chrome, Safari 3 이상 및 Opera 9.6 이상에서 작동합니다
답변
가장 작은 코드로 지금까지의 궁극적 인 접근 방식입니다.
IE9 +, FF, 웹킷 :
MutationObserver 사용 및 필요한 경우 더 이상 사용되지 않는
Mutation 이벤트로 폴백 :
(추가 또는 제거 된 노드와 관련된 DOM 변경의 경우 만 아래 예)
var observeDOM = (function(){
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function( obj, callback ){
if( !obj || !obj.nodeType === 1 ) return; // validation
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
callback(mutations);
})
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
}
else if( window.addEventListener ){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
//------------< DEMO BELOW >----------------
// add item
var itemHTML = "<li><button>list item (click to delete)</button></li>",
listElm = document.querySelector('ol');
document.querySelector('body > button').onclick = function(e){
listElm.insertAdjacentHTML("beforeend", itemHTML);
}
// delete item
listElm.onclick = function(e){
if( e.target.nodeName == "BUTTON" )
e.target.parentNode.parentNode.removeChild(e.target.parentNode);
}
// Observe a specific DOM element:
observeDOM( listElm, function(m){
var addedNodes = [], removedNodes = [];
m.forEach(record => record.addedNodes.length & addedNodes.push(...record.addedNodes))
m.forEach(record => record.removedNodes.length & removedNodes.push(...record.removedNodes))
console.clear();
console.log('Added:', addedNodes, 'Removed:', removedNodes);
});
// Insert 3 DOM nodes at once after 3 seconds
setTimeout(function(){
listElm.removeChild(listElm.lastElementChild);
listElm.insertAdjacentHTML("beforeend", Array(4).join(itemHTML));
}, 3000);
<button>Add Item</button>
<ol>
<li><button>list item (click to delete)</button></li>
<li><button>list item (click to delete)</button></li>
<li><button>list item (click to delete)</button></li>
<li><button>list item (click to delete)</button></li>
<li><em>…More will be added after 3 seconds…</em></li>
</ol>
답변
나는 최근에 정확히 그것을 수행하는 플러그인을 작성했다 -jquery.initialize
.each
함수 와 같은 방식으로 사용 합니다
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
차이점은 .each
선택기 .some-element
입니다.이 경우이 선택 기가있는 새 요소를 기다립니다. 이러한 요소가 추가되면 초기화됩니다.
우리의 경우 초기화 함수는 요소 색상을 파란색으로 변경합니다. 따라서 다음과 같이 새 요소를 추가하면 (아약스 또는 F12 검사기 또는 기타 사항에 관계없이)
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
플러그인은 즉시 초기화합니다. 또한 플러그인은 한 요소가 한 번만 초기화되도록합니다. 따라서 요소를 추가 한 다음 .detach()
본문에서 요소 를 추가 한 다음 다시 추가하면 다시 초기화되지 않습니다.
$("<div/>").addClass('some-element').appendTo("body").detach()
.appendTo(".some-container");
//initialized only once
플러그인은 다음을 기반으로합니다. MutationObserver
– readme 페이지 에 설명 된대로 IE9 및 10에서 종속성으로 작동 합니다 .
답변
또는 어디서나 진행되는 자신 만의 이벤트 를 만들 수 있습니다.
$("body").on("domChanged", function () {
//dom is changed
});
$(".button").click(function () {
//do some change
$("button").append("<span>i am the new change</span>");
//fire event
$("body").trigger("domChanged");
});
답변
이것은 이것에 적응 한 Mozilla의 MutationObserver 를 사용한 예입니다. 블로그 게시물
Chrome 18 세 이상, Firefox 14 이상, IE 11 이상, Safari 6 이상
// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');
// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };
// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
for(var 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
var observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
// Later, you can stop observing
observer.disconnect();
답변
Gabriele Romanato의 블로그에 표시된대로 MutationObserver 인터페이스를 사용하십시오.
Chrome 18 세 이상, Firefox 14 이상, IE 11 이상, Safari 6 이상
// The node to be monitored
var target = $( "#content" )[0];
// Create an observer instance
var observer = new MutationObserver(function( mutations ) {
mutations.forEach(function( mutation ) {
var newNodes = mutation.addedNodes; // DOM NodeList
if( newNodes !== null ) { // If there are new nodes added
var $nodes = $( newNodes ); // jQuery set
$nodes.each(function() {
var $node = $( this );
if( $node.hasClass( "message" ) ) {
// do something
}
});
}
});
});
// Configuration of the observer:
var config = {
attributes: true,
childList: true,
characterData: true
};
// Pass in the target node, as well as the observer options
observer.observe(target, config);
// Later, you can stop observing
observer.disconnect();
답변
이것을 위해 jquery를 확장하는 것은 어떻습니까?
(function () {
var ev = new $.Event('remove'),
orig = $.fn.remove;
var evap = new $.Event('append'),
origap = $.fn.append;
$.fn.remove = function () {
$(this).trigger(ev);
return orig.apply(this, arguments);
}
$.fn.append = function () {
$(this).trigger(evap);
return origap.apply(this, arguments);
}
})();
$(document).on('append', function (e) { /*write your logic here*/ });
$(document).on('remove', function (e) { /*write your logic here*/ ) });
Jquery 1.9+는 이것을 지원합니다 (테스트하지 않은 것으로 들었습니다).