source

모든 jquery 이벤트를 $(문서)로 바인딩해야 합니까?

factcode 2023. 7. 28. 22:56
반응형

모든 jquery 이벤트를 $(문서)로 바인딩해야 합니까?

이것이 어디서 오는 것인지

jQuery를 처음 배울 때는 보통 다음과 같은 이벤트를 첨부했습니다.

$('.my-widget a').click(function() {
    $(this).toggleClass('active');
});

셀렉터 속도와 이벤트 위임에 대해 자세히 알게 된 후 "jQuery 이벤트 위임이 코드를 더 빠르게 만들 것입니다."라는 글을 여러 곳에서 읽었습니다.그래서 저는 다음과 같은 코드를 쓰기 시작했습니다.

$('.my-widget').on('click','a',function() {
    $(this).toggleClass('active');
});

이 방법은 더 이상 사용되지 않는 .live() 이벤트의 동작을 복제하는 권장 방법이기도 합니다.많은 사이트에서 위젯을 항상 동적으로 추가/제거하기 때문에 중요합니다.그러나 위는 .live()와 정확히 다르게 동작합니다. 왜냐하면 이미 존재하는 컨테이너 '.my-widget'에 추가된 요소만 동작을 받기 때문입니다.코드가 실행된 후 HTML 블록을 동적으로 추가하면 해당 요소에 이벤트가 바인딩되지 않습니다.다음과 같이:

setTimeout(function() {
    $('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);


달성하고자 하는 목표:

  1. .live() //의 오래된 동작은 아직 존재하지 않는 요소에 이벤트를 첨부하는 것을 의미합니다.
  2. ...의 이익.
  3. 이벤트 바인딩 속도가 가장 빠름
  4. 간단한 이벤트 관리 방법

이제 다음과 같은 모든 이벤트를 첨부합니다.

$(document).on('click.my-widget-namespace', '.my-widget a', function() {
    $(this).toggleClass('active');
});

제 목표를 모두 충족시키는 것 같습니다.(네, IE에서는 왠지 더 느립니다만, 왜 그런지 모르겠습니다.)단일 요소에 단일 이벤트만 연결되고 2차 셀렉터는 이벤트가 발생할 때만 평가되기 때문에 속도가 빠릅니다(여기서 잘못된 경우 수정 부탁드립니다).네임스페이스는 이벤트 수신기를 쉽게 전환할 수 있기 때문에 훌륭합니다.

내 솔루션/질문

그래서 저는 jQuery 이벤트는 항상 $(문서)로 묶어야 한다고 생각하기 시작했습니다.
당신이 이것을 하고 싶지 않은 이유가 있습니까?
이것이 모범 사례로 간주될 수 있습니까?그렇지 않다면, 왜?

이 모든 것을 읽으셨다면 감사합니다.모든 피드백/견해에 감사드립니다.

가정:

  1. 를 지원하는 를 사용하는 jQuery.on() 1. 이상
  2. 동적으로 추가된 콘텐츠에 이벤트를 추가하려는 경우

판독치/예:

  1. http://24ways.org/2011/your-jquery-now-with-less-suck
  2. http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery
  3. http://www.jasonbuckboyer.com/playground/speed/speed.html
  4. http://api.jquery.com/on/

-된 모든 를 " " - " " 에 안 .document물건. 이 만들수 있는 입니다.그것은 아마도 당신이 만들 수 있는 최악의 수행 시나리오일 것입니다.

먼저, 이벤트 위임이 항상 코드를 더 빠르게 만드는 것은 아닙니다.어떤 경우에는 유리하고 어떤 경우에는 그렇지 않습니다.실제로 이벤트 위임이 필요할 때와 이벤트 위임의 이점을 누릴 때 이벤트 위임을 사용해야 합니다.그렇지 않으면 이벤트 핸들러를 이벤트가 발생하는 개체에 직접 바인딩해야 합니다. 일반적으로 이렇게 하는 것이 더 효율적입니다.

둘째, 문서 수준에서 위임된 모든 이벤트를 바인딩해서는 안 됩니다.이것이 바로 이유입니다..live()이렇게 바인딩된 이벤트가 많은 경우 매우 비효율적이기 때문에 더 이상 사용하지 않습니다.위임된 이벤트 처리의 경우 동적이지 않은 가장 가까운 부모에 바인딩하는 것이 훨씬 효율적입니다.

셋째, 모든 이벤트가 작동하거나 모든 문제가 위임을 통해 해결될 수 있는 것은 아닙니다.예를 들어, 입력 컨트롤의 키 이벤트를 가로채서 잘못된 키가 입력 컨트롤에 입력되는 것을 차단하려는 경우 위임된 이벤트 처리를 사용할 수 없습니다. 이벤트가 위임된 처리기까지 버블이 발생하면 이미 입력 컨트롤에 의해 처리되었기 때문에 해당 동작에 영향을 주기에는 너무 늦기 때문입니다.

다음은 이벤트 위임이 필요하거나 유리한 경우입니다.

  • 이벤트를 캡처하는 개체가 동적으로 생성/제거되고 새 개체를 생성할 때마다 이벤트 핸들러를 명시적으로 다시 바인딩할 필요 없이 해당 개체에 대한 이벤트를 캡처해야 합니다.
  • 모든 개체가 동일한 이벤트 핸들러를 원하는 개체가 많은 경우(여기서 로트는 최소 수백 개).이 경우 설정 시 수백 개 이상의 직접 이벤트 처리기보다 하나의 위임된 이벤트 처리기를 바인딩하는 것이 더 효율적일 수 있습니다.위임된 이벤트 처리는 항상 직접 이벤트 처리기보다 런타임에 효율성이 떨어집니다.
  • 문서의 모든 요소에서 발생하는 이벤트를 (문서의 상위 수준에서) 캡처하려고 할 때.
  • 설계에서 이벤트 버블링을 명시적으로 사용하고 있는 경우 페이지의 일부 문제나 기능을 해결하기 위해 전파()를 중지합니다.

이를 조금 더 이해하기 위해서는 jQuery 위임 이벤트 처리기의 작동 방식을 이해해야 합니다.다음과 같은 것을 부를 때:

$("#myParent").on('click', 'button.actionButton', myFn);

를 jQuery 이일설다에 합니다.#myParent가 이 핸들러로 는 이 핸들러 핸들러의 .클릭 이벤트가 이 위임된 이벤트 핸들러까지 거품이 발생하면 jQuery는 이 개체에 연결된 위임된 이벤트 핸들러 목록을 검토하고 이벤트의 원본 요소가 위임된 이벤트 핸들러의 선택기와 일치하는지 확인해야 합니다.

실렉터가 상당히 관여할 수 있기 때문에 jQuery는 각 실렉터를 구문 분석한 다음 원래 이벤트 대상의 특성과 비교하여 각 실렉터와 일치하는지 확인해야 합니다.이것은 저렴한 수술이 아닙니다.이 중 하나만 있으면 큰 문제가 되지 않지만 문서 개체에 모든 셀렉터를 놓고 모든 버블링 이벤트와 비교할 셀렉터가 수백 개 있으면 이벤트 처리 성능이 심각하게 저하될 수 있습니다.

따라서 위임된 이벤트 핸들러가 대상 개체에 최대한 근접하도록 위임된 이벤트 핸들러를 설정해야 합니다.즉, 위임된 각 이벤트 핸들러를 통해 버블링되는 이벤트 수가 줄어들어 성능이 향상됩니다.모든 버블링된 이벤트는 모든 위임된 이벤트 처리기를 통과하고 가능한 모든 위임된 이벤트 선택기에 대해 평가되어야 하므로 문서 개체에 위임된 모든 이벤트를 배치하는 것은 최악의 성능입니다.이것이 바로 이유입니다..live()이것이 바로 그것이기 때문에 더 이상 사용되지 않습니다..live()했고 그것은 매우 비효율적인 것으로 판명되었습니다.


따라서 최적화된 성능을 달성하기 위해 다음과 같이 하십시오.

  1. 실제로 필요한 기능을 제공하거나 성능을 높이는 경우에만 위임된 이벤트 처리를 사용하십시오.실제로 필요하지 않을 때는 쉽기 때문에 항상 사용하지 마십시오.실제로 이벤트 발송 시간에 직접 이벤트 바인딩보다 성능이 떨어집니다.
  2. 위임된 이벤트 처리기를 이벤트 원본에서 가장 가까운 상위 항목에 가능한 한 연결합니다.이벤트를 캡처할 동적 요소가 있으므로 위임된 이벤트 처리를 사용하는 경우 동적 요소가 아닌 가장 가까운 상위 항목을 선택합니다.
  3. 위임된 이벤트 처리기에 대해 평가하기 쉬운 선택기를 사용합니다.위임된 이벤트 처리 방식을 따르면 위임된 이벤트 처리기를 여러 개체와 비교해야 하므로 최대한 효율적인 선택기를 선택하거나 간단한 선택기를 사용할 수 있도록 개체에 단순 클래스를 추가하면 위임된 이벤트 처리 성능이 향상됩니다.

이벤트 위임은 요소가 실제로 DOM에 존재하기 전에 핸들러를 작성하는 기술입니다.이 방법에는 단점이 있으므로 이러한 요구 사항이 있는 경우에만 사용해야 합니다.

이벤트 위임을 언제 사용해야 합니까?

  1. 동일한 기능이 필요한 더 많은 요소에 대해 공통 핸들러를 바인딩하는 경우(예: 테이블 행 호버)
    • 이 예에서는 직접 바인딩을 사용하여 모든 행을 바인딩해야 하는 경우 해당 테이블에 n개 행에 대한 처리기를 생성하게 됩니다.위임 방법을 사용하면 하나의 간단한 처리기에서 모든 작업을 처리할 수 있습니다.
  2. DOM에서 동적 컨텐츠를 더 자주 추가하는 경우(예: 테이블에서 행 추가/제거)

이벤트 위임을 사용하면 안 되는 이유는 무엇입니까?

  1. 이벤트를 요소에 직접 바인딩하는 것에 비해 이벤트 위임 속도가 느립니다.
    • 대상 선택기가 부딪치는 모든 버블을 비교합니다. 비교는 복잡할 때마다 비용이 많이 듭니다.
  2. 이벤트가 바인딩된 요소에 도달할 때까지 이벤트 버블링을 제어할 수 없습니다.

PS: 동적 콘텐츠의 경우에도 DOM에 콘텐츠가 삽입된 후 핸들러를 바인딩하면 이벤트 위임 방식을 사용할 필요가 없습니다. (동적 콘텐츠가 자주 제거/재추가되지 않는 경우)

jfriend00의 답변에 몇 가지 발언과 반론을 추가하고 싶습니다.(내 직감에 근거한 내 의견만 말해줘요)

아니오 - 위임된 모든 이벤트 처리기를 문서 개체에 바인딩해서는 안 됩니다.그것은 아마도 당신이 만들 수 있는 최악의 수행 시나리오일 것입니다.

먼저, 이벤트 위임이 항상 코드를 더 빠르게 만드는 것은 아닙니다.어떤 경우에는 유리하고 어떤 경우에는 그렇지 않습니다.실제로 이벤트 위임이 필요할 때와 이벤트 위임의 이점을 누릴 때 이벤트 위임을 사용해야 합니다.그렇지 않으면 이벤트 핸들러를 이벤트가 발생하는 개체에 직접 바인딩해야 합니다. 일반적으로 이렇게 하는 것이 더 효율적입니다.

단일 요소에 대한 등록 및 이벤트만 수행할 경우 성능이 약간 향상될 수 있지만, 위임이 제공하는 확장성 이점과 비교할 수 없다고 생각합니다.저는 브라우저가 이 문제를 더욱 더 효율적으로 처리할 것이라고 생각하지만, 이에 대한 증거는 없습니다.제 생각에는 이벤트 위임이 최선의 방법입니다!

둘째, 문서 수준에서 위임된 모든 이벤트를 바인딩해서는 안 됩니다..live()가 더 이상 사용되지 않는 이유는 이러한 방식으로 바인딩된 이벤트가 많은 경우 매우 비효율적이기 때문입니다.위임된 이벤트 처리의 경우 동적이지 않은 가장 가까운 부모에 바인딩하는 것이 훨씬 효율적입니다.

저는 이것에 동의합니다.이벤트가 컨테이너 내부에서만 발생할 것이라고 100% 확신할 경우 이벤트를 이 컨테이너에 바인딩하는 것이 타당하지만 트리거 요소에 이벤트를 직접 바인딩하는 것은 반대합니다.

셋째, 모든 이벤트가 작동하거나 모든 문제가 위임을 통해 해결될 수 있는 것은 아닙니다.예를 들어, 입력 컨트롤의 키 이벤트를 가로채서 잘못된 키가 입력 컨트롤에 입력되는 것을 차단하려는 경우 위임된 이벤트 처리를 사용할 수 없습니다. 이벤트가 위임된 처리기까지 버블이 발생하면 이미 입력 컨트롤에 의해 처리되었기 때문에 해당 동작에 영향을 주기에는 너무 늦기 때문입니다.

이것은 단순히 사실이 아닙니다.다음 코드를 참조하십시오. 펜: https://codepen.io/pwkip/pen/jObGmjq

document.addEventListener('keypress', (e) => {
    e.preventDefault();
});

문서에 키 누르기 이벤트를 등록하여 사용자가 입력하지 못하도록 하는 방법을 설명합니다.

다음은 이벤트 위임이 필요하거나 유리한 경우입니다.

이벤트를 캡처하는 개체가 동적으로 생성/제거되고 새 개체를 생성할 때마다 이벤트 핸들러를 명시적으로 다시 바인딩할 필요 없이 해당 개체에 대한 이벤트를 캡처해야 합니다.모든 개체가 동일한 이벤트 핸들러를 원하는 개체가 많은 경우(여기서 로트는 최소 수백 개).이 경우 설정 시 수백 개 이상의 직접 이벤트 처리기보다 하나의 위임된 이벤트 처리기를 바인딩하는 것이 더 효율적일 수 있습니다.위임된 이벤트 처리는 항상 직접 이벤트 처리기보다 런타임에 효율성이 떨어집니다.

저는 https://ehsangazar.com/optimizing-javascript-event-listeners-for-performance-e28406ad406c 의 이 인용구로 답변을 드리고 싶습니다.

Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.

, 또한위, 을한구링글다음og▁for에 대한 구글링performance cost of event delegation google이벤트 위임을 위해 더 많은 결과를 반환합니다.

문서의 모든 요소에서 발생하는 이벤트를 (문서의 상위 수준에서) 캡처하려고 할 때.설계에서 이벤트 버블링을 명시적으로 사용하고 있는 경우 페이지의 일부 문제나 기능을 해결하기 위해 전파()를 중지합니다.이를 조금 더 이해하기 위해서는 jQuery 위임 이벤트 처리기의 작동 방식을 이해해야 합니다.다음과 같은 것을 부를 때:

$("#MyParent").on('클릭', '버튼.actionButton', myFn);#myParent 개체에 일반 jQuery 이벤트 핸들러를 설치합니다.클릭 이벤트가 이 위임된 이벤트 핸들러까지 거품이 발생하면 jQuery는 이 개체에 연결된 위임된 이벤트 핸들러 목록을 검토하고 이벤트의 원본 요소가 위임된 이벤트 핸들러의 선택기와 일치하는지 확인해야 합니다.

실렉터가 상당히 관여할 수 있기 때문에 jQuery는 각 실렉터를 구문 분석한 다음 원래 이벤트 대상의 특성과 비교하여 각 실렉터와 일치하는지 확인해야 합니다.이것은 저렴한 수술이 아닙니다.이 중 하나만 있으면 큰 문제가 되지 않지만 문서 개체에 모든 셀렉터를 놓고 모든 버블링 이벤트와 비교할 셀렉터가 수백 개 있으면 이벤트 처리 성능이 심각하게 저하될 수 있습니다.

따라서 위임된 이벤트 핸들러가 대상 개체에 최대한 근접하도록 위임된 이벤트 핸들러를 설정해야 합니다.즉, 위임된 각 이벤트 핸들러를 통해 버블링되는 이벤트 수가 줄어들어 성능이 향상됩니다.모든 버블링된 이벤트는 모든 위임된 이벤트 처리기를 통과하고 가능한 모든 위임된 이벤트 선택기에 대해 평가되어야 하므로 문서 개체에 위임된 모든 이벤트를 배치하는 것은 최악의 성능입니다.이것이 바로 .live()가 한 일이고 매우 비효율적이기 때문에 .live()가 더 이상 사용되지 않는 이유입니다.

이것은 어디에 기록되어 있습니까?만약 그것이 사실이라면, jQuery는 매우 비효율적인 방식으로 위임을 처리하고 있는 것처럼 보이며, 그러면 나의 반론은 바닐라 JS에만 적용되어야 합니다.

여전히: 저는 이 주장을 뒷받침하는 공식적인 정보원을 찾고 싶습니다.

편집 ::

jQuery는 실제로 매우 비효율적인 방식으로 이벤트 버블링을 수행하는 것 같습니다(IE8을 지원하기 때문에). https://api.jquery.com/on/ #이벤트-퍼포먼스

그래서 여기서 제 주장의 대부분은 바닐라 JS와 최신 브라우저에만 해당됩니다.

보아하니, 지금은 이벤트 위임이 실제로 권장됩니다. 적어도 바닐라 js에는요.

https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/

"웹 성능 # 문서에서 클릭할 때마다 듣는 것은 성능에 좋지 않은 것처럼 느껴지지만, 실제로는 개별 항목에 대해 많은 이벤트 청취자가 있는 것보다 더 성능이 좋습니다."

언급URL : https://stackoverflow.com/questions/12824549/should-all-jquery-events-be-bound-to-document

반응형