요즘 인터뷰 질문에서 1,000리마다 클릭 이벤트를 추가하라고 하더군요. 대부분의 사람들의 첫인상은 각 리에 클릭 이벤트를 추가하는 것입니다. 경우, 인터뷰 중 GG일 것으로 예상됩니다. 여기서는 이벤트 버블링 및 캡처 메커니즘과 이벤트 위임 메커니즘을 철회했습니다.
먼저 이벤트 버블링과 이벤트 캡처 메커니즘에 대해 이야기해보자. 이벤트 버블링은 마이크로소프트가 제안했고, 이벤트 캡처는 당시 두 회사가 치열하게 논쟁을 벌이던 중 나중에 W3C가 채택할 수밖에 없었다. 이는 이벤트가 생성된 후 먼저 캡처된 다음 버블링됩니다.
일반적으로 js에서 이벤트를 수신하는 세 가지 방법이 있습니다.
ele. addEventListener(type,listener ,[useCapture]);//IE6~8은
ele.attachEvent('on'+type,listener)를 지원하지 않습니다.//IE6~10은 지원하지 않고, IE11은 지원하지 않습니다. support
ele.onClick=function(){};//모든 브라우저 지원
w3c 사양에서는 캡처 단계, 대상 단계, 버블링 단계의 세 가지 이벤트 단계를 정의합니다. , w3c에서 지정한 dom2 수준 규정에서는 addEventListener를 사용하여 이벤트를 수신합니다. 따라서 먼저 addEventListener를 사용하여 설명하겠습니다. 가짜 거품은 물에 돌을 던지면 물 속에 거품이 생기는 것과 같습니다. 아래에서 팝업됩니다. 즉, 이벤트가 트리거된 후 물 속의 거품이 아래에서 올라갑니다. 요소 왕은 상위 요소의 방향으로 트리거되는 반면 캡처 메커니즘은 이벤트를 트리거합니다. 상위 요소에서 하위 요소로, addEventListener 함수의 세 번째 매개변수는 캡처 메커니즘을 사용할지 버블링 메커니즘을 사용할지 결정하는 데 사용됩니다. useCapture가 true이면 캡처 메커니즘이고, useCapture가 false이면 캡처 메커니즘입니다. 버블링 메커니즘이므로 예를 살펴보겠습니다.
코드 복사
<div class="parent"> <div class="child"> </div> </div> <script> var parent = document.getElementsByClassName('parent')[0]; var child = document.getElementsByClassName('child')[0]; parent.addEventListener('click',function(){ console.log("这里是父元素"); },false); child.addEventListener('click',function(){ console.log("这里是子元素"); },false); </script>
하위 요소를 클릭하면 위 그림이 나타납니다. false를 true로 변경하면 실행 순서가 바뀌는 것을 알 수 있습니다. 이것이 이벤트 버블링과 캡처의 차이점입니다.
그러면 이 바인딩 메커니즘을 사용할 때의 단점은 이벤트를 각 객체에 바인딩하는 것이 특히 번거롭다는 것입니다. 이벤트를 삭제하거나 변경하려는 경우 특히 번거로울 것입니다. JavaScript와 DOM 노드 사이에는 언제든지 순환 참조가 발생하므로 메모리 누수가 발생할 수 있습니다. 이것이 단점입니다.
이 단점을 해결하는 방법 중 하나가 이벤트 위임입니다. 각 노드에 이벤트를 하나씩 추가하지 않아도 됩니다. 이러한 수신 이벤트를 해당 노드의 상위 요소에 바인딩하면 상위 요소의 수신 기능이 이벤트를 트리거한 하위 요소를 자동으로 결정합니다. 여기서 제공하는 예는 davidwalsh가 제공한 예입니다.
이제 상위 요소 ul과 여러 li 하위 요소가 있습니다.
<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> </ul>원하는 것 이제 달성해야 할 점은 각 li 노드를 클릭하면 위와 같이 li 노드의 내용이 출력된다는 것입니다. 작성 방법에서는 이러한 li를 선택하고 해당 메서드를 추가한 다음 제거할 수 있습니다. 더 이상 필요하지 않습니다. 100li 또는 1000li가 있으면 이는 악몽이 될 것입니다. 더 나은 해결책은 부모 요소에 청취 이벤트를 추가하는 것입니다. 우리는 어떤 li를 클릭했는지 판단할 수 있습니다. 우리가 찾고 있는 노드인지 확인하기 위해 청취 이벤트의 현재 이벤트 대상을 확인합니다. 여기에 간단한 예가 있습니다.
// 找到父元素,绑定一个监听事件 document.getElementById("parent-list").addEventListener("click", function(e) { // e.target是点击的元素 // 如果它是li元素 if(e.target && e.target.nodeName == "LI") { // console.log("List item ", e.target.id.replace("post-", ""), " was clicked!"); } });
addEventListener가 버블링 이벤트이기 때문에 ul에서 클릭 이벤트가 발생하는 경우 기본적으로 기본 이벤트가 버블링되면 청취 이벤트가 실행됩니다. 이벤트가 트리거된 후 그것이 우리가 찾고 있는 대상 요소인지 여부를 감지하기 위해 그렇지 않은 경우 무시됩니다. 대상 요소의 태그는 우리에게 필요한 대상 요소이지만, 대상 요소의 속성이나 클래스 이름을 기반으로 이를 수행할 수도 있습니다. 처리를 위해
document.getElementById("myDiv").addEventListener("click",function(e) { // e.target 就是当前被点击的元素 if (e.target && e.target.matches("a.classA")) { console.log("Anchor element clicked!"); } });따라서 이벤트 프록시를 사용하면 많은 편리함을 얻을 수 있고 많은 함정을 피할 수 있다는 것을 알 수 있습니다. 이벤트 위임을 사용하는 것은 매우 강력한 방법입니다.