DOM 이벤트 위임이란 무엇입니까?


202

누구든지 JavaScript로 이벤트 위임을 설명 할 수 있으며 어떻게 유용합니까?


2
이것에 관한 유용한 정보 소스에 대한 링크가 있다면 좋을 것입니다. 6 시간 후, 이것은 "dom event delegation"에 대한 구글의 인기입니다. 아마도 이것이 유용한 링크일까요? 확실하지 않습니다 : w3.org/TR/DOM-Level-2-Events/events.html
Sean McMillan


7
이것은 인기있는 것입니다. 심지어 fb 놈들도 그들의 reactjs 페이지 davidwalsh.name/event-delegate
Sorter

javascript.info/event-delegation를 참조하면 많은 도움이 될 것입니다
Suraj Jain

답변:


330

DOM 이벤트 위임은 이벤트 "버블 링"(일명 이벤트 전파)의 마법을 통해 각 자식이 아닌 단일 공통 부모를 통해 UI 이벤트에 응답하는 메커니즘입니다.

요소에서 이벤트가 트리거 되면 다음이 발생합니다 .

이벤트가 대상으로 전달되고 EventTarget이벤트 리스너가 발견되면 트리거됩니다. 버블 링 이벤트는 다음에 의해 발견 된 추가 이벤트 리스너 트리거 EventTarget의 부모 체인을 위로 각 연속의 EventTarget에 등록 된 모든 이벤트 리스너 확인을. 이 상향 전파는 Document.

이벤트 버블 링은 브라우저에서 이벤트 위임을위한 기초를 제공합니다. 이제 이벤트 핸들러를 단일 상위 요소에 바인드 할 수 있으며 해당 핸들러는 이벤트가 하위 노드 (및 해당 하위 노드)에서 발생할 때마다 실행됩니다 . 이것은 이벤트 위임입니다. 실제 사례는 다음과 같습니다.

<ul onclick="alert(event.type + '!')">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
</ul>

이 예제에서 하위 <li>노드 를 클릭하면 클릭 "click!"<li>사용자 에게 바인딩 된 클릭 핸들러가 없더라도 경고가 표시 됩니다. 우리 onclick="..."가 서로 <li>를 묶으면 같은 효과를 얻을 수 있습니다.

이점은 무엇입니까?

<li>DOM 조작을 통해 위의 목록에 새 항목을 동적으로 추가해야한다고 상상해보십시오 .

var newLi = document.createElement('li');
newLi.innerHTML = 'Four';
myUL.appendChild(newLi);

이벤트 위임을 사용 하지 않으면 형제와 같은 방식으로 작동하기 위해 "onclick"이벤트 핸들러를 새 <li>요소 에 "리 바인드" 해야합니다 . 이벤트 위임을 사용하면 아무 것도 할 필요가 없습니다. <li>목록에 새 항목 을 추가하면 완료됩니다.

DOM에서 새로운 요소가 동적으로 생성 및 / 또는 제거되는 많은 요소에 이벤트 핸들러가 바인딩 된 웹 앱에는 매우 환상적입니다. 이벤트 위임을 통해 이벤트 바인딩 수를 공통 상위 요소로 이동하여 이벤트 바인딩 수를 크게 줄일 수 있으며, 새 요소를 동적으로 작성하는 코드를 이벤트 핸들러 바인딩 논리에서 분리 할 수 ​​있습니다.

이벤트 위임의 또 다른 이점은 이벤트 리스너가 사용하는 총 메모리 풋 프린트가 줄어든다는 것입니다 (이벤트 바인딩 수가 줄어듦). 자주 언로드되는 작은 페이지 (예 : 사용자가 다른 페이지를 자주 탐색)와 크게 차이가 없을 수 있습니다. 그러나 수명이 긴 애플리케이션의 경우 중요 할 수 있습니다. DOM에서 제거 된 요소가 여전히 메모리를 요구하는 (즉, 누출) 추적하기 어려운 상황이 종종 있으며,이 누출 된 메모리는 종종 이벤트 바인딩에 연결됩니다. 이벤트 위임을 사용하면 이벤트 리스너를 "바인드 해제"하는 것을 잊어 버릴 위험없이 하위 요소를 자유롭게 제거 할 수 있습니다 (리스너가 조상에 있으므로). 그런 다음 이러한 유형의 메모리 누수를 포함시킬 수 있습니다 (제거하지 않으면 때로는 어려운 일입니다. IE가보고 있습니다).

이벤트 위임에 대한보다 구체적인 코드 예제는 다음과 같습니다.


나는 마지막 링크에 대한 자바 스크립트 라이브러리와 하나없이 세 번째 링크 이벤트 위임을 여는 금지 액세스 가지고있다
bugwheels94

안녕하세요, 좋은 설명 감사합니다. 그래도 특정 세부 사항에 대해 혼란 스럽습니다 .DOM 트리 이벤트 흐름을 이해하는 방식 ( 3.1 이벤트 디스패치 및 DOM 이벤트 흐름 에서 볼 수 있음 ) 이벤트 객체는 대상 요소에 도달 할 때까지 전파되어 거품이 생깁니다. 이 노드의 부모가 문제의 이벤트 대상인 경우 어떻게 노드의 하위 요소에 도달 할 수 있습니까? 예를 들어 이벤트가 <li>언제 중지되어야 <ul>합니까? 내 질문이 여전히 명확하지 않거나 별도의 스레드가 필요한 경우 기꺼이 준수해야합니다.
Aetos

@Aetos : >이 노드의 부모가 문제의 이벤트 대상이라면 어떻게 노드의 자식 요소에 도달 할 수 있습니까? 내가 알기로는 불가능합니다. 이벤트는 대상의 상위에서 1 단계 (캡처)를 마치고 대상 자체에서 2 단계 (대상)로 들어간 다음 대상의 상위에서 시작하여 3 단계 (버블 링)로 들어갑니다. 대상의 자식에는 도달하지 않습니다.
Crescent Fresh

@Crescent 신선한 다음 이벤트가 자식 노드에 도달하지 않으면 어떻게 자식 노드에 적용됩니까?
Aetos

1
정말 좋은 답변입니다. 관련 사실과 함께 이벤트 위임을 설명해 주셔서 감사합니다. 감사!
Kshitij Tiwari

30

이벤트 위임을 사용하면 특정 노드에 이벤트 리스너를 추가하지 않아도됩니다. 대신 이벤트 리스너가 하나의 상위에 추가됩니다. 해당 이벤트 리스너는 버블 링 된 이벤트를 분석하여 하위 요소에서 일치하는 항목을 찾습니다.

자바 스크립트 예제 :

여러 하위 요소가있는 상위 UL 요소가 있다고 가정 해 보겠습니다.

<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>

또한 각 하위 요소를 클릭하면 무언가가 발생해야한다고 가정 해 봅시다. 각 개별 LI 요소에 별도의 이벤트 리스너를 추가 할 수 있지만 LI 요소가 목록에서 자주 추가되고 제거되면 어떻게됩니까? 특히 추가 및 제거 코드가 앱 내 다른 위치에있는 경우 이벤트 리스너를 추가 및 제거하는 것은 악몽입니다. 더 나은 솔루션은 이벤트 리스너를 부모 UL 요소에 추가하는 것입니다. 그러나 이벤트 리스너를 부모에게 추가하면 어떤 요소가 클릭되었는지 어떻게 알 수 있습니까?

단순 : 이벤트가 UL 요소까지 버블 링되면 실제 클릭 된 노드에 대한 참조를 얻기 위해 이벤트 오브젝트의 대상 특성을 확인합니다. 다음은 이벤트 위임을 보여주는 매우 기본적인 JavaScript 스 니펫입니다.

// Get the element, add a click listener...
document.getElementById("parent-list").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a list item
if(e.target && e.target.nodeName == "LI") {
    // List item found!  Output the ID!
    console.log("List item ", e.target.id.replace("post-"), " was clicked!");
       }
 });

클릭 이벤트 리스너를 부모 요소에 추가하여 시작하십시오. 이벤트 리스너가 트리거되면 이벤트 요소가 반응 할 요소 유형인지 확인하십시오. LI 요소라면 붐 : 우리는 우리가 필요로하는 것을 가지고 있습니다! 원하는 요소가 아닌 경우 이벤트를 무시할 수 있습니다. 이 예제는 매우 간단합니다. UL과 LI는 간단한 비교입니다. 더 어려운 것을 시도합시다. 많은 자녀를 둔 부모 DIV가 있지만 우리가 걱정하는 것은 classA CSS 클래스의 A 태그입니다.

  // Get the parent DIV, add click listener...
  document.getElementById("myDiv").addEventListener("click",function(e) {
// e.target was the clicked element
if(e.target && e.target.nodeName == "A") {
    // Get the CSS classes
    var classes = e.target.className.split(" ");
    // Search for the CSS class!
    if(classes) {
        // For every CSS class the element has...
        for(var x = 0; x < classes.length; x++) {
            // If it has the CSS class we want...
            if(classes[x] == "classA") {
                // Bingo!
                console.log("Anchor element clicked!");
                // Now do something here....
            }
        }
    }

  }
});

http://davidwalsh.name/event-delegate


1
권장 조정 : 마지막 예에서는 e.classList.contains ()를 사용하십시오 ( developer.mozilla.org/en-US/docs/Web/API/Element/classList
nc).

7

돔 이벤트 위임 은 컴퓨터 과학 정의와는 다릅니다.

테이블 셀과 같은 많은 요소, 테이블과 같은 부모 개체의 버블 링 이벤트 처리를 나타냅니다. 특히 요소를 추가하거나 제거 할 때 코드를 더 단순하게 유지하고 메모리를 절약 할 수 있습니다.


6

대표단 은 개체가 외부에 특정 동작을 표현하지만 실제로는 해당 동작을 구현할 책임을 관련 개체에 위임하는 기술입니다. 이것은 처음에는 프록시 패턴과 매우 비슷하게 들리지만 훨씬 다른 목적으로 사용됩니다. 위임은 객체 (방법) 동작을 중앙 집중화하는 추상화 메커니즘입니다.

일반적으로 사용 : 상속의 대안으로 위임을 사용하십시오. 상속은 부모와 자식 개체 사이에 밀접한 관계가있을 때 상속하는 좋은 전략이지만 상속은 개체를 매우 밀접하게 연결합니다. 종종 위임은 수업 사이의 관계를 표현하는 더 유연한 방법입니다.

이 패턴은 "프록시 체인"이라고도합니다. 다른 여러 디자인 패턴은 위임을 사용합니다. 상태, 전략 및 방문자 패턴은 그에 따라 다릅니다.


좋은 설명입니다. <li> 자녀가 여러 명인 <ul>의 예에서 분명히 <li>는 클릭 논리를 처리하는 것이지만 아버지 <ul>에서이 논리를 "위임"하기 때문에 그렇지 않습니다
Juanma Menendez

6

위임 개념

하나의 부모 안에 많은 요소가 있고 그 요소에 대한 이벤트를 처리하려면 처리기를 각 요소에 바인딩하지 마십시오. 대신 단일 처리기를 부모에 바인딩하고 event.target에서 자식을 가져옵니다. 이 사이트는 이벤트 위임을 구현하는 방법에 대한 유용한 정보를 제공합니다. http://javascript.info/tutorial/event-delegation


6

이벤트 위임이 거품나는 이벤트를 처리 중입니다. 컨테이너 요소에서 이벤트 핸들러를 사용하여 하지만 지정된 조건과 일치하는 컨테이너 내의 요소에서 이벤트가 발생한 경우에만 이벤트 핸들러의 작동을 활성화합니다. 컨테이너 내의 요소에 대한 이벤트 처리를 단순화 할 수 있습니다.

예를 들어, 큰 테이블에서 테이블 셀에 대한 클릭을 처리하려고한다고 가정하십시오. 넌 할 수있어 각 셀에 클릭 핸들러를 연결하는 루프를 작성 ...하거나 테이블 헤더, 또는 내에서 공백 만 테이블 셀을 트리거 테이블 사용 이벤트 위임에 클릭 핸들러를 연결 (그리고 수 셀 주변 행 등).

컨테이너에서 요소를 추가하고 제거 할 때도 유용합니다. 해당 요소에서 이벤트 핸들러를 추가하고 제거하는 것에 대해 걱정할 필요가 없기 때문입니다. 컨테이너에 이벤트를 연결하고 버블이 발생하면 이벤트를 처리하십시오.

다음은 간단한 예입니다 (인라인 설명을 허용하기 위해 의도적으로 자세합니다). td컨테이너 테이블의 모든 요소에 대한 클릭 처리 :

// Handle the event on the container
document.getElementById("container").addEventListener("click", function(event) {
    // Find out if the event targeted or bubbled through a `td` en route to this container element
    var element = event.target;
    var target;
    while (element && !target) {
        if (element.matches("td")) {
            // Found a `td` within the container!
            target = element;
        } else {
            // Not found
            if (element === this) {
                // We've reached the container, stop
                element = null;
            } else {
                // Go to the next parent in the ancestry
                element = element.parentNode;
            }
        }
    }
    if (target) {
        console.log("You clicked a td: " + target.textContent);
    } else {
        console.log("That wasn't a td in the container table");
    }
});
table {
    border-collapse: collapse;
    border: 1px solid #ddd;
}
th, td {
    padding: 4px;
    border: 1px solid #ddd;
    font-weight: normal;
}
th.rowheader {
    text-align: left;
}
td {
    cursor: pointer;
}
<table id="container">
    <thead>
        <tr>
            <th>Language</th>
            <th>1</th>
            <th>2</th>
            <th>3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th class="rowheader">English</th>
            <td>one</td>
            <td>two</td>
            <td>three</td>
        </tr>
        <tr>
            <th class="rowheader">Español</th>
            <td>uno</td>
            <td>dos</td>
            <td>tres</td>
        </tr>
        <tr>
            <th class="rowheader">Italiano</th>
            <td>uno</td>
            <td>due</td>
            <td>tre</td>
        </tr>
    </tbody>
</table>

자세한 내용을 살펴보기 전에 DOM 이벤트의 작동 방식을 상기시켜 보겠습니다.

DOM 이벤트는 문서에서 대상 요소 ( 캡처 단계) 로 전달 된 다음 대상 요소에서 문서로 다시 버블 링됩니다 ( 버블 링 단계). 이전 DOM3 이벤트 사양 의이 그래픽 (현재 대체되었지만 그래픽은 여전히 ​​유효 함)이 실제로 잘 표시합니다.

여기에 이미지 설명을 입력하십시오

모든 이벤트가 버블 링되는 것은 아니지만를 포함하여 대부분의 이벤트가 발생합니다 click.

위 코드 예제의 주석은 작동 방식을 설명합니다. matches요소가 CSS 선택기와 일치하는지 확인하지만 CSS 선택기를 사용하지 않으려는 경우 다른 방법으로 기준과 일치하는지 여부를 확인할 수 있습니다.

그 코드는 자세하게 각 단계를 호출하도록 작성되어 있지만, (당신이 polyfill을 사용하는 경우 또한 IE에) 희미하게-최신 브라우저에, 당신은 사용 closest하고 contains대신 루프 :

var target = event.target.closest("td");
    console.log("You clicked a td: " + target.textContent);
} else {
    console.log("That wasn't a td in the container table");
}

라이브 예 :

closest주어진 CSS 선택자와 일치하는지 확인하기 위해 호출하는 요소를 확인하고 일치하는 경우 동일한 요소를 리턴합니다. 그렇지 않은 경우 부모 요소가 일치하는지 확인하고 일치하는 경우 부모 요소를 반환합니다. 그렇지 않은 경우 부모의 부모 등을 확인합니다. 따라서 상위 목록에서 선택기와 일치하는 "가장 가까운"요소를 찾습니다. 컨테이너 요소를 지날 수 있기 때문에 위의 코드 contains는 일치하는 요소가 발견되면 컨테이너 내에 있는지 확인하는 데 사용 합니다. 컨테이너에 이벤트를 연결하면 해당 컨테이너 내의 요소 만 처리하려는 것으로 표시 되었으므로 .

테이블 예제로 돌아가서, 테이블 셀 내에 테이블이 있으면 테이블을 포함하는 테이블 셀과 일치하지 않음을 의미합니다.


3

기본적으로 요소와의 연결 방법입니다. 이벤트 위임 후 DOM에 추가 된 새 요소에 대해서는 위임을 사용하여 .click현재 DOM에 .on계속 적용됩니다 .

사용하는 것이 더 낫습니다. 경우에 따라 다릅니다.

예:

<ul id="todo">
   <li>Do 1</li>
   <li>Do 2</li>
   <li>Do 3</li>
   <li>Do 4</li>
</ul>

클릭 이벤트 :

$("li").click(function () {
   $(this).remove ();
});

이벤트 :

$("#todo").on("click", "li", function () {
   $(this).remove();
});

.on에서 선택기를 분리했습니다. 이유를 설명하겠습니다.

이 연결 후에 다음을 수행한다고 가정 해 봅시다.

$("#todo").append("<li>Do 5</li>");

그것이 차이점을 알 수있는 곳입니다.

이벤트가 .click을 통해 연결된 경우 작업 5는 클릭 이벤트를 따르지 않으므로 제거되지 않습니다.

.on을 통해 연결된 경우 선택기가 별도 인 경우 준수합니다.


2

이벤트 위임을 이해하려면 먼저 이벤트 위임이 필요한 이유와시기를 알아야합니다.

많은 경우가있을 수 있지만 이벤트 위임에 대한 두 가지 큰 사용 사례에 대해 논의 해 봅시다. 1. 첫 번째 경우는 관심있는 하위 요소가 많은 요소가있는 경우입니다.이 경우 모든 하위 요소에 이벤트 핸들러를 추가하는 대신 단순히 상위 요소에 추가 한 다음 결정합니다. 어떤 하위 요소에서 이벤트가 시작되었는지

2. 이벤트 위임의 두 번째 사용 사례는 페이지가로드 될 때 아직 DOM에없는 요소에 이벤트 핸들러를 첨부하려는 경우입니다. 물론 페이지에없는 것에 이벤트 핸들러를 추가 할 수 없기 때문에 더 이상 사용하지 않을 경우 코딩하고 있습니다.

페이지를로드 할 때 DOM에 0, 10 또는 100 개의 항목 목록이 있고 더 많은 항목이 목록에 추가되기를 기다리고 있다고 가정합니다. 따라서 미래 요소에 대한 이벤트 핸들러를 첨부 할 수있는 방법이 없거나 해당 요소가 DOM에 아직 추가되지 않았고 많은 항목이있을 수 있으므로 각 이벤트 핸들러를 하나씩 첨부하는 것이 유용하지 않습니다. 그들의.

이벤트 위임

이벤트 위임에 대해 이야기하기 위해 실제로 이야기해야 할 첫 번째 개념은 이벤트 버블 링입니다.

이벤트 버블 링 : 이벤트 버블 링은 일부 DOM 요소에서 이벤트가 시작되거나 트리거 될 때 (예 : 아래 이미지에서 여기에있는 단추를 클릭 함) 모든 상위 요소에서 정확히 동일한 이벤트가 트리거됨을 의미합니다.

여기에 이미지 설명을 입력하십시오

이벤트는 먼저 버튼에서 시작되지만 모든 부모 요소에서도 한 번에 하나씩 발생하므로 단락의 주요 요소 섹션에서 실제로 DOM 트리에서 시작됩니다. 루트 인 HTML 요소까지 우리는 이벤트가 DOM 트리 내에서 버블 링되는 것을 버블 링이라고 부릅니다.

1 2 삼 4

대상 요소 : 이벤트가 실제로 발생한 요소를 대상 요소라고하며, 이벤트를 일으킨 요소를 대상 요소라고합니다. 위의 예에서, 이것은 물론 클릭 된 버튼입니다. 중요한 부분은이 대상 요소가 이벤트 객체에 속성으로 저장된다는 것입니다. 즉, 이벤트가 시작될 모든 상위 요소가 이벤트의 대상 요소를 알고 이벤트가 처음 발생한 위치를 알게됩니다.

이벤트 가 DOM 트리에서 버블 링되고 이벤트가 발생한 위치를 알면 단순히 이벤트 핸들러를 상위 요소에 연결하고 이벤트가 버블 링 될 때까지 기다릴 수 있기 때문에 이벤트 위임 이 가능합니다. 그런 다음 대상 요소로 수행하려는 모든 작업을 수행하십시오. 이 기술을 이벤트 위임이라고합니다. 이 예제에서는 이벤트 핸들러를 기본 요소에 간단히 추가 할 수 있습니다.

다시, 이벤트 위임은 우리가 관심있는 원래 요소에 이벤트 핸들러를 설정하지 않고 부모 요소에 첨부하고 기본적으로 이벤트가 발생하기 때문에 이벤트를 잡는 것입니다. 그런 다음 대상 요소 속성 사용에 관심이있는 요소에 대해 작업 할 수 있습니다.

예 : 이제 페이지에 두 개의 목록 항목이 있다고 가정 해 봅시다. 프로그래밍 방식으로 목록에 항목을 추가 한 후 하나 이상의 항목을 삭제하려고합니다. 이벤트 위임 기술을 사용하여 목적을 쉽게 달성 할 수 있습니다.

<div class="body">
    <div class="top">

    </div>
    <div class="bottom">
        <div class="other">
            <!-- other bottom elements -->
        </div>
        <div class="container clearfix">
            <div class="income">
                <h2 class="icome__title">Income</h2>
                <div class="income__list">
                    <!-- list items -->
                </div>
            </div>
            <div class="expenses">
                <h2 class="expenses__title">Expenses</h2>
                <div class="expenses__list">
                    <!-- list items -->
                </div>
            </div>
        </div>
    </div>
</div>

해당 목록에 항목 추가하기 :

const DOMstrings={
        type:{
            income:'inc',
            expense:'exp'
        },
        incomeContainer:'.income__list',
        expenseContainer:'.expenses__list',
        container:'.container'
   }


var addListItem = function(obj, type){
        //create html string with the place holder
        var html, element;
        if(type===DOMstrings.type.income){
            element = DOMstrings.incomeContainer
            html = `<div class="item clearfix" id="inc-${obj.id}">
            <div class="item__description">${obj.descripiton}</div>
            <div class="right clearfix">
                <div class="item__value">${obj.value}</div>
                <div class="item__delete">
                    <button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
                </div>
            </div>
        </div>`
        }else if (type ===DOMstrings.type.expense){
            element=DOMstrings.expenseContainer;
            html = ` <div class="item clearfix" id="exp-${obj.id}">
            <div class="item__description">${obj.descripiton}</div>
            <div class="right clearfix">
                <div class="item__value">${obj.value}</div>
                <div class="item__percentage">21%</div>
                <div class="item__delete">
                    <button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
                </div>
            </div>
        </div>`
        }
        var htmlObject = document.createElement('div');
        htmlObject.innerHTML=html;
        document.querySelector(element).insertAdjacentElement('beforeend', htmlObject);
    }

항목 삭제 :

var ctrlDeleteItem = function(event){
       // var itemId = event.target.parentNode.parentNode.parentNode.parentNode.id;
        var parent = event.target.parentNode;
        var splitId, type, ID;
        while(parent.id===""){
            parent = parent.parentNode
        }
        if(parent.id){
            splitId = parent.id.split('-');
            type = splitId[0];
            ID=parseInt(splitId[1]);
        }

        deleteItem(type, ID);
        deleteListItem(parent.id);
 }

 var deleteItem = function(type, id){
        var ids, index;
        ids = data.allItems[type].map(function(current){
            return current.id;
        });
        index = ids.indexOf(id);
        if(index>-1){
            data.allItems[type].splice(index,1);
        }
    }

  var deleteListItem = function(selectorID){
        var element = document.getElementById(selectorID);
        element.parentNode.removeChild(element);
    }

1

C #의 대리자는 C 또는 C ++의 함수 포인터와 유사합니다. 델리게이트를 사용하면 프로그래머가 델리게이트 객체 내부의 메서드에 대한 참조를 캡슐화 할 수 있습니다. 그러면 델리게이트 개체를 컴파일 타임에 호출 할 메서드를 몰라도 참조 된 메서드를 호출 할 수있는 코드로 전달할 수 있습니다.

이 링크 참조-> http://www.akadia.com/services/dotnet_delegates_and_events.html


5
원래 질문에 대한
정답

1

이벤트 위임은 자주 발생하는 두 가지 JavaScript 이벤트 기능인 이벤트 버블 링 및 대상 요소를 사용합니다. 이벤트가 요소 (예 : 마우스 클릭 단추)에서 트리거되면 동일한 이벤트가 해당 요소의 모든 조상에서 트리거됩니다. . 이 프로세스를 이벤트 버블 링이라고합니다. 이벤트는 원래 요소에서 DOM 트리의 맨 위로 버블 링됩니다.

사용자가 테이블 셀을 클릭 할 때 발생하는 열과 열이 100 개인 HTML 테이블을 상상해보십시오. 예를 들어, 한 번 클릭하면 해당 크기의 표의 각 셀을 편집 가능하게 만들어야했습니다. 1000 개의 각 셀에 이벤트 핸들러를 추가하면 성능 문제가 발생하고 브라우저 충돌 메모리 누수가 발생할 수 있습니다. 대신 이벤트 위임을 사용하면 테이블 요소에 하나의 이벤트 핸들러 만 추가하고 클릭 이벤트를 가로 채서 클릭 한 셀을 판별합니다.


0
이벤트 위임

자식 요소에서 이벤트가 발생할 때 발생하는 부모 요소에 이벤트 리스너를 연결하십시오.

이벤트 전파

이벤트가 DOM을 통해 하위 요소에서 상위 요소로 이동하는 경우 이벤트가 전파되거나 DOM을 통해 이동하기 때문에 이를 이벤트 전파 라고 합니다.

이 예제에서 버튼의 이벤트 (클릭시)는 상위 단락으로 전달됩니다.

$(document).ready(function() {

    $(".spoiler span").hide();

    /* add event onclick on parent (.spoiler) and delegate its event to child (button) */
    $(".spoiler").on( "click", "button", function() {
    
        $(".spoiler button").hide();    
    
        $(".spoiler span").show();
    
    } );

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<p class="spoiler">
    <span>Hello World</span>
    <button>Click Me</button>
</p>

코드 펜

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