2012-07-11 7 views
8

다음 코드는 DOM 변경 이벤트 DOMNodeInserted을 사용하여 body 요소의 존재를 감지하고 innerHTML을 래퍼로 래핑합니다. DOM 돌연변이 관찰자는 DOM 돌연변이 이벤트보다 느립니다?

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 
    <script> 
     function DOMmanipulation() { 
      if (document.body) { 
       document.removeEventListener('DOMNodeInserted', DOMmanipulation); 
       // DOM manipulation start 
       document.body.innerHTML = '<div class="wrapper">' + document.body.innerHTML + '</div>'; 
       // DOM manipulation end 
      } 
     } 
     document.addEventListener('DOMNodeInserted', DOMmanipulation); 
    </script> 
</head> 
<body> 
    <p>Lorem ipsum dolor sit amet.</p> 
</body> 
</html> 

그리고 포장의 성공에도 불구하고

는 오류가 노드가 발견되지 않았 음을 보여주고있다. This answer은 jQuery가로드되었을 때 어떤 테스트를 수행하기 위해 div 요소를 본문에 추가했으나 해당 요소가 래퍼에 래핑되었으므로 해당 요소가 제거되지 않았기 때문에 div 요소를 제거하지 못했습니다. 더 이상 신체의 자식 요소.

위의 실험은 DOMNodeInserted 이벤트가 jQuery를 제거 할 수 있습니다 전에 jQuery의 테스트 요소 (div가) 포장 얻었 기 때문에 jQuery의 테스트보다 더 빠르다는 것을 우리에게 알려줍니다.




이제 다음 코드는 같은 조작을 달성 할 수 있으며, 새로 도입 DOM 돌연변이 관찰자를 사용하고. 이번 (2012-07-11) 현재 Chrome 18 이상에서만 작동합니다.

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 
    <script> 
     var observer = new WebKitMutationObserver(function() { 
      if (document.body) { 
       observer.disconnect(); 
       // DOM manipulation start 
       document.body.innerHTML = '<div class="wrapper">' + document.body.innerHTML + '</div>'; 
       // DOM manipulation end 
      } 
     }); 
     observer.observe(document, { subtree: true, childList: true }); 
    </script> 
</head> 
<body> 
    <p>Lorem ipsum dolor sit amet.</p> 
</body> 
</html> 

이 코드는 오류를 발생시키지 않습니다. 즉, jQuery는 DOM Mutation Observers보다 빠르기 때문에 테스트 요소 (div)를 제거한 다음 해당 요소를 래퍼에 래핑 할 수있었습니다.


는 위의 두 실험에서



, 우리는 찾아 그 그것은 실행 속도에 관해서 :

  • DOM 돌연변이 이벤트 > jQuery의 테스트
  • jQuery의 테스트 > DOM 변이 관찰자

DOM Mutation Observers가 DOM Mutation Events보다 느리다는 것을 적절하게 증명할 수 있습니까?

답변

24

DOM 변경 관찰자는 DOM 변경 이벤트보다 빠르지 않습니다. 오히려 그것들은보다 효율적이고 안전하도록 만들어졌습니다.

차이점의 기본 요지는 변경 될 때마다 DOM Mutation Events가 실행된다는 것입니다. 예를 들어,이 코드는 콜백 루프를 생성하여 궁극적으로 브라우저를 손상시킵니다.

document.addEventListener('DOMNodeInserted', function() { 
    var newEl = document.createElement('div'); 
    document.body.appendChild(newEl); 
}); 

그들은 이런 식으로 호출하고 브라우저 사이의 인터럽트를 강제로 너무 자주 또한, 브라우저에 상당한 효과가 있다는 사실 스타일, 리플 로우를 다시 계산하고 다시 계산주기 또는 더 나쁜 세력에게 브라우저를 다시 칠 스타일, 리플 로우 및 모든 콜백에서 다시 칠하기. 문제는 다른 코드가 실행되어 콜백에 의해 계속 중단 될 DOM을 추가로 변경한다는 사실에 의해 더욱 분노하게됩니다.

이벤트가 일반 DOM 이벤트와 같은 방식으로 전파되기 때문에 관심이 없거나 코드에서 고려하지 않은 요소에 대한 변경 사항을 듣기 시작할 것입니다. DOM 돌연변이 이벤트의 전체 메커니즘은 매우 신속하게 관리하기 위해 번거로울 수 있습니다.

DOM 변경 관찰자는 DOM의 변경 사항을 관찰하고 변경 사항의 시작부터 발생한 모든 변경 사항에 대한 보고서를 제공하기 때문에 이러한 문제를 해결합니다. 예를 들어 문서가 유휴 상태이고 추가 변경을 할 수있는 다른 모든 JavaScript가 실행을 마쳤거나 브라우저가 브라우저를 다시 시작하기 전에 브라우저가 한 번에 알리도록 허용하는 것이 훨씬 좋은 상황입니다. recalc/repaint cycle을 사용하여주기를 반복하지 않고 변경 사항을 적용 할 수 있습니다.

변경 사항을 모두 조사하여 원하는 것을 찾을 수 있기 때문에 관리하기가 더 쉽습니다. 신경 쓰지 않는 코드를 다루는 사례를 많이 작성하는 대신 Mutation Events의 상황이었습니다. 더 중요하게는 한 번만 호출 할 것이므로 더 이상 변경 사항이 요소에 영향을 미치므로 요소가 더 이상 상태를 변경하지 않고 변경되었음을 염려 할 필요가 없습니다.

귀하의 질문에 대한 답변으로, DOM 변경 관찰자는 jQuery가 변경된 jQuery를 알려주기 전에 jQuery가 DOM 조작을 완료하기를 기다렸기 때문에 속도가 느립니다. 위에 설명 된 이유와 예제를 통해 더 안전하고 효율적인 솔루션 (더 이상 오류가 발생하지 않음)이 입증되었으며, jQuery가 DOM에 뭔가를 추가 한 사실에 신경 쓰지 않았습니다. 곧 제거되었을 것이기 때문입니다. Observers를 사용하면 jQuery 요소를 추가 및 제거하는 방법을 자세히 설명하는 보고서를 받게됩니다.

그러나 실제로 발생하는 모든 변경 사항과 요소를 일치 시켜서 실제로 어떤 일이 발생했는지 파악해야하기 때문에 이는 다소 번거로운 작업입니다. 현실은 당신이 걱정하지 않는 한 (동일한 요소가 추가되고 제거 된) 아무 일도 일어나지 않았으므로 DOM의 구조가 실제로 변경되지 않았습니다. 변화의 순 효과를 계산하고 변경 사항 만 전달 콜백을 호출

http://code.google.com/p/mutation-summary/

이 돕기 위해 MutationSummary라는 작은 도서관이있다. 따라서 귀하의 경우 콜백은 전혀 호출되지 않았을 것입니다. 변경의 순 효과가 0이기 때문입니다.

예. 다음에 대해서는 단 하나의 변경 만 받게됩니다. 바디 스타일이 왼쪽 : 1000px로 변경되었습니다. 비록 내가 1000 단위로 그것을 바 꾸었습니다. 변경의 최종 효과는 초기 값과 최종 값의 차이뿐입니다.

function moveBody() { 
    for (var i = 0; i < 1000; i++) document.body.style.left = i + 'px'; 
} 
moveBody(); 
+0

감사합니다. @AshHeskes와 좋은 설명을 많이했습니다! 마침내 저는 그들의 사형 원리를 이해합니다. –

6

간단한 대답은 돌연변이 관찰자가 비동기 적이라는 것입니다. 엔진이 변경 될 때마다 엔진이 느껴질 때마다, 변화가 일어난 후 어떤 경우에는 그리고 많은 경우에 많은 변화가 발생한 후에 보냈습니다. DOM 변이 이벤트 리스너가 당신에게 알린 후에 오랜 시간이 걸릴 수 있습니다. 그러나 엔진은 매 순간마다 변경되는 DOM 변경에 대해 끊임없이 이벤트를 작성하고 버블 링하지 않고도 작업을 완료 할 수 있습니다.

+0

고맙다 Nartowicz! –