ProgramingTip

전체 DOM에서 노드를 감지하는 MutationObserver의 성능

bestdevel 2020. 12. 29. 07:41
반응형

전체 DOM에서 노드를 감지하는 MutationObserver의 성능


MutationObserver특정 HTML 요소가 HTML 페이지의 아무 곳에 나 추가 감지하는 데 사용 하는 데 관심 이 있습니다. 예를 들어 <li>, DOM의 어느 곳에 나가 추가, 감지하고 싶다고 말씀 드리겠습니다 .

MutationObserver지금까지 본 모든 예제는 노드가 특정 컨테이너에 추가 여부를 감지합니다. 예를 들면 :

일부 HTML

<body>

  ...

  <ul id='my-list'></ul>

  ...

</body>

MutationObserver 정의

var container = document.querySelector('ul#my-list');

var observer = new MutationObserver(function(mutations){
  // Do something here
});

observer.observe(container, {
  childList: true,
  attributes: true,
  characterData: true,
  subtree: true,
  attributeOldValue: true,
  characterDataOldValue: true
});

이에 따라 예에서는 MutationObserver매우 많은 컨테이너 ( ul#my-list)를 감시하여 <li>'가 추가로 확인 하도록 설정합니다.

구체적 덜 이고 다음과 <li>같이 전체 HTML 본문 에서 의를 보려면 문제가 있습니까?

var container = document.querySelector('body');

내가 직접 설정하는 기본 예제에서 작동한다는 것을 알고 있습니다.하지만이 작업을 권장하지 않습니다. 이로 인해 성능이 입증 되었습니까? 성능 문제를 어떻게 감지하고 측정 할 수 있습니까?

모든 MutationObserver예제가 대상 컨테이너에 너무 거기 이라는 이유가 존재한다고 확신하지 않습니다.


이 옵션은 복잡한 페이지에 적용됩니다.

페이지로드가 시작되기 전에 관찰자는 (입니다 부착되어 특히 경우 document_start/ document-start크롬 확장 / WebExtensions / userscripts 아니면 그냥 일반 동기 페이지 펼쳐 내부에서 <head>) 더 많은 동적으로 업데이트 된 페이지 예를 들어 분기에 GitHub의. 최적화되지 않은 Mutation Observer ( 1 , 2 ) 페이지가 몇 시간에 초를 추가 할 수 있습니다 . 대부분의 기존의 기존 라이브러리는 사용하기 쉽지만 느린 js 코드를 제공합니다.

MutationObserver는 DOM의 추가 처리를 차단하는 마이크로 실행되고 복잡한 페이지에서 초당 수백 번 실행될 수 있습니다.

  1. 항상 devtools 러를 사용하고 관찰자되는 전체 CPU 시간의 1 %를 사용합니다.

  2. offsetTop 및 최적화 속성에 액세스하여 강제 동기 레이아웃 트리거링 방지

  3. jQuery와 같은 복잡한 DOM 프레임 워크 / 라이브러리 사용을 피하고 기본 DOM 항목을 선호합니다.

  4. 속성을 관찰 할 때에 서 attributeFilter: ['attr1', 'attr2']옵션을 사용하십시오 .observe().

  5. 가능하면 직계 부모를 비재 귀적으로 관찰하십시오 ( subtree: false).
    예를 들어, document재귀 적으로 관찰 하여 새로운 부모 요소를 기다렸다가 성공시 관찰자의 연결을 고이 컨테이너 요소에 비 재귀 요소를 연결하는 것이 좋습니다.

  6. 로 한 요소를 사용할 경우 id속성, 미친 듯이를 사용하여 빠른 getElementById 대신 열거의 mutations배열 (이 항목의 수천 수 있습니다) : .

  7. 경우 원하는 요소 페이지 (를 들어 상대적 예으로 드문 iframe또는 object) 라이브 HTMLCollection 의해 반환 된에 사용 getElementsByTagNamegetElementsByClassName그들을 다시 확인 모든 대신 의 열거 mutations가 예를 들어 100 개 이상의 요소가있는 경우.

  8. querySelector특히 매우 느린 사용을 피하십시오 querySelectorAll.

  9. querySelectorAllMutationObserver 내에서 절대적 콜백으로 피할 수없는 경우 먼저 querySelector확인을 수행하고 성공하면 querySelectorAll. 평균적으로 콤보는 훨씬 빠를 것입니다.

  10. 블리딩이 아닌 엣지 브라우저를 대상으로하는 경우, forEach, 필터 어셈블리 같은 내장 메소드를 사용하지 않고 필요합니다. Chrome의 V8에서는 기존의 함수가 항상 클래식 for (var i=0 ....)루프에 비해 호출 비용이 많이 들었 기 때문입니다 (10-100 배 더 느림). ,하지만 V8 팀이 작업 중입니다 [2017]). MutationObserver 일련의 복잡한 최신 페이지의 각 변이 배치 addedNodes에서 100 개의 실행될 수 있습니다 .

    배열 내장의 인라인은 일반적으로 벤치 마크와 기본 코드에서 발생합니다. 실제 세계에서 MutationObserver는 활동이 간헐적으로 급증하며 (예 : 1 ~ 1000 개의 노드가 초당 100 회보고 됨) 더이 return x * x단순하지 않은 단일 코드가 인라인 / 최적화가 "핫"으로 감지되지 않습니다.

    lodash 또는 유사한 빠른 라이브러리가 지원하는 대체 기능 열거는 괜찮습니다. 2018 년부터 Chrome 및 기본 V8은 표준 배열 기본 제공 메서드를 인라인합니다.

  11. 블리딩이 아닌 엣지 브라우저를 대상으로 하는 경우 결과 코드가 클래식 루프 만큼 빠르게 실행되도록 트랜스 파일하지 않는 한 MutationObserver 콜백 내부 와 같이 느린 ES2015 루프를 사용하지 마십시오 .for (let v of something)for

  12. 목표가 페이지 모양을 변경하는 것이며 추가되는 요소가 페이지의 보이는 부분 밖에 있음을 알리는 안정적이고 빠른 방법이있는 경우 관찰자를 연결 해제하고 setTimeout(fn, 0)다음을 통해 전체 페이지 재확인 및 재 처리를 예약하십시오 . 파싱 ​​/ 레이아웃 활동의 초기 버스트가 완료되고 엔진은 1 초도 걸릴 수있는 "호흡"할 수 있습니다. 그런 다음 예를 들어 requestAnimationFrame을 사용하여 페이지를 청크 단위로 눈에 띄지 않게 처리 할 수 ​​있습니다.

질문으로 돌아 가기 :

어떤 컨테이너 가 추가 ul#my-list되었는지 확인하기 위해 매우 특정 컨테이너 를 관찰하십시오 <li>.

li직계 자식 이므로 추가 된 노드를 찾기 때문에 필요한 유일한 옵션childList: true위의 조언 # 2를 참조하십시오.

new MutationObserver(function(mutations, observer) {
    // Do something here

    // Stop observing if needed:
    observer.disconnect();
}).observe(document.querySelector('ul#my-list'), {childList: true});

참조 URL : https://stackoverflow.com/questions/31659567/performance-of-mutationobserver-to-detect-nodes-in-entire-dom

반응형