일부 div 또는 입력이 HTML에 추가되면 함수를 실행하고 싶습니다. 이게 가능해?
예를 들어, 텍스트 입력이 추가되면 함수를 호출해야합니다.
일부 div 또는 입력이 HTML에 추가되면 함수를 실행하고 싶습니다. 이게 가능해?
예를 들어, 텍스트 입력이 추가되면 함수를 호출해야합니다.
답변:
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>
mutations, observer
더 컨트롤에 대한 콜백 함수에 매개 변수를.
나는 최근에 정확히 그것을 수행하는 플러그인을 작성했다 -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+는 이것을 지원합니다 (테스트하지 않은 것으로 들었습니다).