특정 클래스의 div를 감지하는 jquery가 DOM에 추가되었습니다.


91

.on()페이지가로드 된 후 생성되는 div의 이벤트를 바인딩 하는 데 사용 하고 있습니다. click, mouseenter ...에 대해 잘 작동하지만 MyClass 클래스의 새 div가 추가 된시기를 알아야합니다. 나는 이것을 찾고 있어요 :

$('#MyContainer').on({

  wascreated: function () { DoSomething($(this)); }

}, '.MyClass');

어떻게해야합니까? 플러그인없이 전체 앱을 작성해 왔으며 그대로 유지하고 싶습니다.

감사.


요소를 생성하는 자체 코드입니까? 그렇다면 그것을 만들 때 확인하고 그에 따라 행동 할 수 있습니다.
Surreal Dreams

예, 사실입니다.하지만 .on ()을 사용하면 document.ready에서 이벤트를 바인딩 할 수 있으며 HTML을 생성 할 때 바인딩에 대해 걱정할 필요가 없습니다. DoSomething과 동일한 동작을 찾고 있습니다.
frenchie

$ ( "div / your-selector"). hasClass ( "MyClass");를 사용할 수 있습니다. div에 특정 클래스가 있는지 확인합니다. 이 API를 사용할 수 있다고 생각합니다.
KBN

.on ()은 이벤트 전용입니다. 사용자 지정 이벤트를 설정할 수 있지만 새 요소를 만들 때 해당 이벤트를 트리거해야합니다.
Surreal Dreams

답변:


104

이전에는 jQuery의 domManip메소드에 연결하여 모든 jQuery dom 조작을 포착하고 삽입 된 요소 등을 확인할 수 있었지만 jQuery 팀은 일반적으로 jQuery 메소드에 연결하는 좋은 솔루션이 아니기 때문에 jQuery 3.0 이상에서이를 종료했습니다. 내부 domManip메서드는 더 이상 핵심 jQuery 코드 외부에서 사용할 수 없도록 만들었습니다 .

Mutation Events는 이전과 같이 사용되지 않습니다.

$(document).on('DOMNodeInserted', function(e) {
    if ( $(e.target).hasClass('MyClass') ) {
       //element with .MyClass was inserted.
    }
});

이것은 피해야하며, 오늘은 Mutation Observers를 대신 사용해야합니다.

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation)
        if (mutation.addedNodes && mutation.addedNodes.length > 0) {
            // element added to DOM
            var hasClass = [].some.call(mutation.addedNodes, function(el) {
                return el.classList.contains('MyClass')
            });
            if (hasClass) {
                // element has class `MyClass`
                console.log('element ".MyClass" added');
            }
        }
    });
});

var config = {
    attributes: true,
    childList: true,
    characterData: true
};

observer.observe(document.body, config);

파이어 폭스와 웹킷은 괜찮지 만 IE에서는 이에 대한 지원이 다소 부족합니다. IE9에서는 작동하지만 IE8에서는 그다지 작동하지 않을 것입니다. 나는 해결 방법을 보았고 IE에서 이것을 실제로 테스트하지 않았으므로 먼저 테스트하고 작동하지 않으면 해결 방법이 있는지 확인하십시오. 여기에 IE 지원을 추가하는 것처럼 보이는 플러그인이 있지만 시도하지 않고 Google 검색에서 찾았습니다.
adeneo

2
처음에는 귀하의 답변을 사용했지만 브라우저 간 작동하지 않는다는 사실이 문제였습니다. 그런 다음 처음에이 문제를 피할 수있는 해결 방법을 빠르게 알아 냈습니다. 그리고 몇 주 전에 노드 삽입 감지 문제가 내 코드에서 다시 나타났습니다. 이번에는 내 답변에 게시 한 코드가 브라우저 간 및 버그가없는 것처럼 정확히 작동합니다. 그래서 내가 대답을 수락 한 것으로 옮겼습니다. 그것이 SO 작동 방식이며 OP는 그가 수락하는 답변을 결정하고 군중은 답변에 투표합니다. 시간이 지남에 따라 사람들은 투표하고 자신에게 가장 적합한 답변을 결정할 것입니다.
frenchie

2
그리고 저의 하루를 구한 고품질 답변으로 저를 여러 번 도와 주셨다 고 말하고 싶었습니다. 내 대답을 변경하는 것은 순전히 코드와 내가 해결해야했던 문제에 어떻게 부합하는지에 기초합니다.
frenchie

이 코드로 "Uncaught TypeError : Cannot read property 'contains of undefined"가 발생했습니다
gordie

53

여기 내 플러그인이 있습니다 -jquery.initialize

사용법은 .each함수를 사용하는 것과 동일 하지만 .initialize요소에 대한 함수를 사용 .each하면 AJAX 등으로 추가하더라도 향후 추가 코드없이 추가 된 요소도 초기화된다는 점이 다릅니다 .

Initialize는 .each 함수와 정확히 동일한 구문을 갖습니다.

$(".some-element").initialize( function(){
    $(this).css("color", "blue");
});

그러나 이제 .some-element selector와 일치하는 새 요소가 페이지에 나타나면 인스턴스가 초기화됩니다. 새 항목이 추가되는 방식은 중요하지 않으며 콜백 등에 대해 신경 쓸 필요가 없습니다.

$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!

플러그인은 MutationObserver


정말 고맙습니다.
Brandon Harris

초기화를 중지하는 방법? 내가 ... 내가 찾던 물건이 추가되면 시청을 중지하려면
예브게니 보스 토크

$ ( ". some-element"). initialize [..]는 더 이상 사용되지 않습니다. $ .initialize ( ". addDialog", function () {$ ( '. noData'). hide ();}); 사용 대신.
Heimi

동적으로 추가 된 요소 (예 : Ajax를 통해)에 대해서만.initialize 함수 를 실행 하고 페이지가 처음로드 될 때 이미있는 요소에 대한 콜백을 건너 뛸 수 있습니까? 이 작업을 수행하기 위해 매개 변수를 추가하려고 하지만 지금까지 작동하지 않았습니다. callback options
Nevermore

그것에 대해 github에 문제를 추가 할 수 있습니다. 지금은 기술적으로 할 수 있습니다$('.myClass').addClass('ignore-initialize'); $.initialize('.myClass:not(.ignore-initialize)', callback);
pie6k

19

이것과 다른 여러 포스트를 검토 한 후, 각각의 최고라고 생각하는 것을 간단한 것으로 추출하여 요소 클래스가 삽입 될 때이를 감지 하고 해당 요소에 대해 조치취했습니다 .

function onElementInserted(containerSelector, elementSelector, callback) {

    var onMutationsObserved = function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                var elements = $(mutation.addedNodes).find(elementSelector);
                for (var i = 0, len = elements.length; i < len; i++) {
                    callback(elements[i]);
                }
            }
        });
    };

    var target = $(containerSelector)[0];
    var config = { childList: true, subtree: true };
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    var observer = new MutationObserver(onMutationsObserved);    
    observer.observe(target, config);

}

onElementInserted('body', '.myTargetElement', function(element) {
    console.log(element);
});

저에게 중요한 점은 a) 대상 요소가 "addedNodes"내의 모든 깊이에 존재하고 b) 처음 삽입 될 때만 요소를 처리 할 수있는 기능 (전체 문서 설정을 검색하거나 "이미 처리됨"을 무시할 필요가 없음) 플래그).


1
귀하의 조건은해야 if(mutation.addedNodes.length)하기 때문에 addedNodesremovedNodes배열은 항상있다 mutation유형 childList(IE11, Chrome53, FF49에서 확인). 여전히 +1, addedNodes고려 되는 유일한 답변이기 때문에 ( callback노드가 추가 될 때만 호출됩니다). 이 스레드뿐만 아니라 다른 많은 스레드에서. callback노드가 삭제되는 경우에도 다른 모든 사람은 모든 변형에 대해 를 호출합니다 .
Vivek Athalye 2016 년

17

3 년 후, "DOM에 추가 된 특정 클래스의 요소"를 듣는 방법입니다 . 다음 html()과 같이 jQuery 함수에 후크를 추가하기 만하면됩니다 .

function Start() {

   var OldHtml = window.jQuery.fn.html;

   window.jQuery.fn.html = function () {

     var EnhancedHtml = OldHtml.apply(this, arguments);

     if (arguments.length && EnhancedHtml.find('.MyClass').length) {

         var TheElementAdded = EnhancedHtml.find('.MyClass'); //there it is
     }

     return EnhancedHtml;
   }
}

$(Start);

이것은 내가하는 jQuery를 사용하는 경우 작동합니다. 그리고 브라우저 DOMNodeInserted간 호환되지 않는 브라우저 별 이벤트에 의존하지 않습니다 . 나는 또한 동일한 구현을 추가했습니다..prepend()

전반적으로 이것은 나에게 매력처럼 작동하며 당신에게도 희망적입니다.


6
흠- html일반적으로 "jQuery 사용"이 아니라 DOM을 수정하기 위해 jQuery의 도우미를 독점적으로 사용하는 경우 이것이 작동 함을 분명히합니다 . 예를 들어를 사용하여 추가 된 요소 jQuery.append는이 이벤트를 트리거하지 않습니다.
iameli

1
예, 당신은으로 .Append 사용하는 경우 내가 .preprend (와 같은 구현을 추가 한 것이 분명) 왜의 ()는 다음으로 .Append ()와 같은 일을 수행하는 것이
프렌치

CSS3 애니메이션을 사용하는 훨씬 더 빠른 접근 방식이 있습니다 . 오픈 소스 라이브러리는 훨씬 간단 코드를 준다 :insertionQ('#intercom-container').every(function(/element){ element.style.display = 'none'; });
댄 Dascalescu에게

3
왜 반대표 ?? 이것은 실제로 작동합니다. 플러그인 및 해키 setTimeout 기능이 없습니다.
프렌치

2
Upvoted-이것은 유효한 옵션입니다-왜 세상에서 (!!!) 이것이 downvoted 되었습니까 ?????? Dan, CSS3 애니메이션은 XBC가 아닙니다 : caniuse.com/#search=keyframes ; davidwalsh.name/detect-node-insertion .
Cody

6

돌연변이 이벤트를 사용할 수 있습니다.

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents

편집하다

MDN에서 : https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events

더 이상 사용되지 않음이 기능은 웹에서 제거되었습니다. 일부 브라우저는 여전히 지원할 수 있지만 삭제 중입니다. 이전 또는 새 프로젝트에서 사용하지 마십시오. 이를 사용하는 페이지 또는 웹 앱은 언제든지 중단 될 수 있습니다.

Mutation Observers는 DOM4의 돌연변이 이벤트에 대한 제안 된 대체입니다. Firefox 14 및 Chrome 18에 포함됩니다.

https://developer.mozilla.org/en/docs/Web/API/MutationObserver

MutationObserver개발자에게 DOM의 변경 사항에 대응하는 방법을 제공합니다. DOM3 이벤트 사양에 정의 된 돌연변이 이벤트를 대체하기 위해 설계되었습니다.

사용 예

다음 예제는 http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/ 에서 가져 왔습니다 .

// select the target node
var target = document.querySelector('#some-id');

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});

// 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();

2
돌연변이 이벤트는 거의에 따라되지 않습니다 MDN MutationObservers 찬성,
올가

이제 IE10이 EOL이므로 MutationObserver 가 광범위하게 지원 된다고 말하는 것이 거의 안전합니다 .
rymo

0

adeneo의 답변에 두 가지 추가 사항 :

(1) 우리는 선을 바꿀 수 있습니다

return el.classList.contains('MyClass');

if( el.classList ) {
    return el.classList.contains('MyClass');
} else {
    return false;
}

따라서 우리는 "Uncaught TypeError: Cannot read property 'contains' of undefined"오류를 보지 않을 것 입니다.

(2) 추가 subtree: true하여 config추가 된 모든 요소에서 추가 된 노드를 재귀 적으로 찾습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.