2009-04-03 8 views
6

필자는 코드 성능 튜닝을하고 있으며 병목 현상이 dom 노드 삽입이 아니라 선택이라는 사실에 놀랐습니다.dom 요소를 얻는 가장 빠른 방법은 무엇입니까?

이 빠르다 :

var row = jquery(rowHTML).appendTo(oThis.parentTable); 

그러나 "행"내부 요소의 점점 후속 느린 :

var checkbox = jquery(".checkbox input", row); 

내가 그래서 내가 첨부 할 수있는 모든 행의 체크 박스를 얻을 필요 그것에 대한 이벤트 핸들러. 확인란을 선택하면 ALMOST 10X AS SLOW가 부모 행 전체를 삽입합니다.

내가 뭘 잘못하고 있니?

+0

ummm. 이것은 이상합니다. 두 사람이 나에게 실용적인 해결책을 주었지만 그때 그들의 게시물은 사라졌다. 어쨌든, 선택자에서 클래스 이름을 제거하면 엄청나게 속도가 빨라질 것 같습니다. 이벤트 위임을 사용하는 Christoph의 대답은 실제로 나에게 가장 잘 보이지만 더 큰 변화입니다. – morgancodes

답변

1

입력란 자체에 클래스 이름을 입력 해보십시오. 그것은 더 빠를 것입니다.

그 이유는 코드가 모든 .checkbox 클래스를 거치며 그 요소의 입력 하위를 찾고 반환한다는 것입니다. 나는 그 행동이 당신의 범인이라고 생각합니다.

입력 필드에있는 클래스로 모든 요소를 ​​찾고 있으면 속도가 향상 될 수 있습니다.

2
var checkbox = jquery(".checkbox input", row); 

이것은 전체 dom 트리를 탐색하여 확인란을 찾습니다. 선택기를 브라우저 native getElementById 기능을 사용할 수있는 ID로 변경하여 속도를 향상시킬 수 있습니다.

var checkbox = jquery("#checkbox input", row); 

다음 예제와 같이 DOM 검색의 시작점으로 행을 사용할 수도 있습니다. 이제 전체 DOM 트리를 다시 파싱하여 일치하는 요소를 찾습니다.

var row = jquery(rowHTML).appendTo(oThis.parentTable); 
row.children(".checkbox input"); 
+0

re : 전체 DOM 트리를 순회하는 것인가? "행"의 자식 노드 만 순회하지 않습니까? – annakata

+0

두 번째 "행"인수를 추가하면 jquery가 전체 DOM 트리를 통과하지 못하게되어 내 행 요소로 시작됩니다. 나는 틀린가? – morgancodes

+0

흠, 네 오른쪽 morgancodes, 나는 몇 가지 테스트를 할거야. 주로 테이블 행이나 div를 사용하고 있습니까? – jfar

1

Sly을 사용해보십시오. 성능에 중점을두고 있습니다.

2

이벤트 위임을 사용하고 확인란 자체가 아닌 상위 요소에 단일 처리기를 추가하십시오.

jQuery는 live() 함수를 통해이를 지원합니다.

+0

좋은 아이디어. 이런 식으로 사건 처리에 접근하는 것은 나에게 결코 발생하지 않았다. – morgancodes

+0

@morgancodes : 이벤트 버블 링에 거의 독점적으로 이벤트 위임을 사용하고 대부분의 리스너를 문서 (이벤트 계층의 루트)에 추가하기 시작했습니다. 비효율적 일 수 있습니다 (이벤트 리스너에 상관없이 모든 리스너가 실행됩니다), 매우 편리합니다 (예 : 적재 해킹이 필요 없음) – Christoph

13

DOM 조작이 간단한 작업을 수행하는 기본 함수를 사용합니다. 브라우저 공급 업체는이를 최적화합니다. HTML에서 행을 빌드하고 있습니다. 내부적으로 jQuery는 .innerHTML을 사용하여 브라우저의 메가 패스트 파서에 패치를 적용합니다.

JS 코드가 DOM을 반복적으로 반복해야하기 때문에 선택이 비교적 느립니다. 최신 브라우저에는 셀렉터 기반 JS에 비약적인 속도 향상을 제공하는 기본 선택 처리 기능이 있습니다. 이 시간이지나 감에 따라 문제는 줄어들 것입니다.쿼리 질문 $(".checkbox input", row)에서, 분해 방법은 다음과

은 다음과 같습니다

  1. row.getElementsByTagName('*');
  2. 가 루프의 모든 요소를 ​​통해 (모든 행 내의 요소)와 /(\s|^)checkbox(\s|$)/와 테스트 elements[i].className를 반환했습니다.
  3. for-loop 모든 요소가 아직 남아 있고 수집 할 수 있습니다. matched[i].getElementsByTagName('input');
  4. 고유 컬렉션.

jQuery 1.3에서는 엔진이 선택기를 통해 다른 방향으로 이동하기 때문에 모든 입력 요소를 가져온 다음 부모 요소를 테스트하는 것과 다릅니다.

JS 선택기 엔진이 CSS에서 실제로 사용할 수있는 것보다 더 많은 CSS 선택기 사양을 구현한다는 점을 다시 말해보십시오 (또는 현재 브라우저에서 구현 됨). 이것을 이용하고, 엔진의 지식, 우리는 선택이 몇 가지 다른 방법으로 최적화 할 수 있습니다 최적화 할 수 있습니다

당신이 어떤 요소가 .checkbox 입력 알고 있다면이 것은 :

$("td.checkbox input", row); 

더 빠른 필터입니다 처음에는 유형에 대해, 그런 다음 일치하는 클래스에 대해서만. 이것은 요소의 매우 작은 하위 집합에는 적용되지 않지만 실용 사례에서는 거의 발생하지 않습니다.

단일 클래스 테스트는 일반적인 것 중 가장 느립니다. selectors people actually use.

간단한 선택 :

$("input[type=checkbox]", row); 

한 루프는 두 개의 루프보다 빠릅니다. 이것은 입력 요소를 찾은 다음 유형 속성별로 직접 필터링합니다. 하위/하위 요소는 절대로 사용되지 않으므로 고유를 건너 뛸 수도 있습니다 (스마트 엔진은 고유 한 속도가 느리기 때문에이를 수행하려고 시도합니다).

더 직접적인 선택기 : 더 직접적인 경우가

$("td:first.checkbox input", row); 

보다 복잡한 선택 실제 속도 (YMMV) 일 수있다. 애프터까지 혼자 말 대신에 행을 통해 반복, 모든 일에 체크 박스 검색의 그들을 두는 것이 이것에 의하여

:

가능한 경우, 테이블 레벨로 검색 컨텍스트를 이동

$("tr td:first.checkbox input", table); 

이의 요점은 반복 선택기 엔진을 발사의 오버 헤드를 제거하는 것입니다, 대신에 하나의 어획량 모든 것을 할 : 루프 다음 ​​한 번에 모두 선택합니다. 이것은 엄청난 속도 향상을 가져올 것이라고 생각하는 것보다는 완벽을 위해 여기에 제시됩니다.

은 선택하지 마십시오 :

당신이가는대로 이벤트를 할당 비트에서 행을 구축 할 수 있습니다.

var row = $('<tr></tr>'); 
var cell = $('<td class="checkbox"></td>').appendTo(row); 
$('<input type="checkbox" name="..."/>').appendTo(cell).click(/* ... */); 

이것은 Ajax 또는 다른 템플릿을 제어 할 수없는 이유로 불가능할 수 있습니다. 또한 속도는 코드를 이런 종류의 혼란으로 바꿀만한 가치가 없을 수도 있지만 때로는 이것이 의미가있을 수 있습니다.

또는이 모두가 효과가 없거나 성능이 너무 좋아지면 메소드를 완전히 다시 생각해 볼 때가 있습니다. 대신 당 요소 인스턴스의 트리 위로 높은 이벤트 리스너를 할당하고이 이벤트를 잡을 수 있습니다

$('table').change(function(e){ 
    // you may want a faster check... 
    if ($(e.target).is('input[type=checkbox]')) { 
    // do some stuff ... 
    } 
}); 

당신이하지 않는 한 아무것도 할 때까지하지 않는이 방법은, 사용자가 실제로 요청합니다. 가장 빠릅니다. :-)

+0

와우. 길고 훌륭한 대답. 이걸 소화하려면 잠깐 필요해. 감사합니다 Borgar! – morgancodes

+0

필자는 선택기 엔진을 작성했기 때문에이 부분에 대해 몇 가지 사실을 알게되었습니다. :-) – Borgar

+0

깊이있는 설명 주셔서 감사합니다. –

0

DOM 요소를 얻는 가장 빠른 방법은 순수한 JavaScript를 사용하고 ID로 호출하는 것입니다.

var element = document.getElementById('element); 
관련 문제